#include "H5Smodule.h"
#include "H5private.h"
#include "H5CXprivate.h"
#include "H5Eprivate.h"
#include "H5FLprivate.h"
#include "H5Iprivate.h"
#include "H5MMprivate.h"
#include "H5Spkg.h"
#include "H5VMprivate.h"
#define H5S_HYPER_COMPUTE_B_NOT_A 0x01
#define H5S_HYPER_COMPUTE_A_AND_B 0x02
#define H5S_HYPER_COMPUTE_A_NOT_B 0x04
#define H5S_HYPER_ADVANCE_SPAN(recover, curr_span, next_span) \
do { \
H5S_hyper_span_t *saved_next_span = (next_span); \
\
\
if(recover) { \
H5S__hyper_free_span(curr_span); \
(recover) = FALSE; \
} \
\
\
(curr_span) = saved_next_span; \
} while(0)
#define H5S_HYPER_PROJ_INT_ADD_SKIP(UDATA, ADD, ERR) \
do { \
\
if((UDATA)->nelem > 0) \
if(H5S__hyper_proj_int_build_proj(UDATA) < 0) \
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, ERR, "can't add elements to projected selection") \
(UDATA)->skip += (ADD); \
} while(0)
typedef hsize_t hbounds_t;
typedef struct {
const H5S_hyper_span_t *ds_span[H5S_MAX_RANK];
hsize_t ds_low[H5S_MAX_RANK];
H5S_hyper_span_info_t *ps_span_info[H5S_MAX_RANK];
uint32_t ps_clean_bitmap;
unsigned ss_rank;
unsigned ds_rank;
unsigned depth;
hsize_t skip;
hsize_t nelem;
uint64_t op_gen;
hbool_t share_selection;
} H5S_hyper_project_intersect_ud_t;
#if H5S_MAX_RANK > 32
#error H5S_MAX_RANK too large for ps_clean_bitmap field in H5S_hyper_project_intersect_ud_t struct
#endif
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 H5S_hyper_span_info_t *H5S__hyper_new_span_info(unsigned rank);
static H5S_hyper_span_info_t *H5S__hyper_copy_span_helper(
H5S_hyper_span_info_t *spans, unsigned rank, unsigned op_info_i,
uint64_t op_gen);
static H5S_hyper_span_info_t *H5S__hyper_copy_span(H5S_hyper_span_info_t *spans,
unsigned rank);
static hbool_t H5S__hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1,
const H5S_hyper_span_info_t *span_info2);
static void H5S__hyper_free_span_info(H5S_hyper_span_info_t *span_info);
static void H5S__hyper_free_span(H5S_hyper_span_t *span);
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, hsize_t startblock,
hsize_t numblocks, hsize_t *buf);
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_info_t **span_tree,
unsigned ndims, hsize_t low, hsize_t high, H5S_hyper_span_info_t *down);
static herr_t H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans,
H5S_hyper_span_info_t *b_spans, unsigned selector,
unsigned ndims, 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_helper(H5S_hyper_span_info_t *spans,
unsigned op_info_i, uint64_t op_gen);
static hsize_t H5S__hyper_spans_nelem(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 herr_t H5S__hyper_generate_spans(H5S_t *space);
static hbool_t H5S__check_spans_overlap(const H5S_hyper_span_info_t *spans1,
const H5S_hyper_span_info_t *spans2);
static herr_t H5S__fill_in_new_space(H5S_t *space1, H5S_seloper_t op,
H5S_hyper_span_info_t *space2_span_lst, 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__set_regular_hyperslab(H5S_t *space, const hsize_t start[],
const hsize_t *app_stride, const hsize_t app_count[], const hsize_t *app_block,
const hsize_t *opt_stride, const hsize_t opt_count[], const hsize_t *opt_block);
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__hyper_iter_get_seq_list_gen(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_iter_get_seq_list_opt(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_iter_get_seq_list_single(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_proj_int_build_proj(H5S_hyper_project_intersect_ud_t *udata);
static herr_t H5S__hyper_proj_int_iterate(const H5S_hyper_span_info_t *ss_span_info,
const H5S_hyper_span_info_t *sis_span_info, hsize_t count, unsigned depth,
H5S_hyper_project_intersect_ud_t *udata);
static void H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride,
hsize_t *count, hsize_t *block, hsize_t clip_size);
static hsize_t H5S__hyper_get_clip_extent_real(const H5S_t *clip_space,
hsize_t num_slices, hbool_t incl_trail);
static herr_t H5S__hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
static herr_t H5S__hyper_release(H5S_t *space);
static htri_t H5S__hyper_is_valid(const H5S_t *space);
static hsize_t H5S__hyper_span_nblocks(H5S_hyper_span_info_t *spans);
static hssize_t H5S__hyper_serial_size(const H5S_t *space);
static herr_t H5S__hyper_serialize(const H5S_t *space, uint8_t **p);
static herr_t H5S__hyper_deserialize(H5S_t **space, const uint8_t **p);
static herr_t H5S__hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
static herr_t H5S__hyper_offset(const H5S_t *space, hsize_t *offset);
static int H5S__hyper_unlim_dim(const H5S_t *space);
static herr_t H5S__hyper_num_elem_non_unlim(const H5S_t *space,
hsize_t *num_elem_non_unlim);
static htri_t H5S__hyper_is_contiguous(const H5S_t *space);
static htri_t H5S__hyper_is_single(const H5S_t *space);
static htri_t H5S__hyper_is_regular(const H5S_t *space);
static htri_t H5S__hyper_shape_same(const H5S_t *space1, const H5S_t *space2);
static htri_t H5S__hyper_intersect_block(const H5S_t *space, const hsize_t *start,
const hsize_t *end);
static herr_t H5S__hyper_adjust_u(H5S_t *space, const hsize_t *offset);
static herr_t H5S__hyper_adjust_s(H5S_t *space, const hssize_t *offset);
static herr_t H5S__hyper_project_scalar(const H5S_t *space, hsize_t *offset);
static herr_t H5S__hyper_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset);
static herr_t H5S__hyper_iter_init(const H5S_t *space, H5S_sel_iter_t *iter);
static herr_t H5S__hyper_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords);
static herr_t H5S__hyper_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end);
static hsize_t H5S__hyper_iter_nelmts(const H5S_sel_iter_t *iter);
static htri_t H5S__hyper_iter_has_next_block(const H5S_sel_iter_t *sel_iter);
static herr_t H5S__hyper_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem);
static herr_t H5S__hyper_iter_next_block(H5S_sel_iter_t *sel_iter);
static herr_t H5S__hyper_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq,
size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
static herr_t H5S__hyper_iter_release(H5S_sel_iter_t *sel_iter);
const H5S_select_class_t H5S_sel_hyper[1] = {{
H5S_SEL_HYPERSLABS,
H5S__hyper_copy,
H5S__hyper_release,
H5S__hyper_is_valid,
H5S__hyper_serial_size,
H5S__hyper_serialize,
H5S__hyper_deserialize,
H5S__hyper_bounds,
H5S__hyper_offset,
H5S__hyper_unlim_dim,
H5S__hyper_num_elem_non_unlim,
H5S__hyper_is_contiguous,
H5S__hyper_is_single,
H5S__hyper_is_regular,
H5S__hyper_shape_same,
H5S__hyper_intersect_block,
H5S__hyper_adjust_u,
H5S__hyper_adjust_s,
H5S__hyper_project_scalar,
H5S__hyper_project_simple,
H5S__hyper_iter_init,
}};
const unsigned H5O_sds_hyper_ver_bounds[] = {
H5S_HYPER_VERSION_1,
H5S_HYPER_VERSION_1,
H5S_HYPER_VERSION_2
};
static const H5S_sel_iter_class_t H5S_sel_iter_hyper[1] = {{
H5S_SEL_HYPERSLABS,
H5S__hyper_iter_coords,
H5S__hyper_iter_block,
H5S__hyper_iter_nelmts,
H5S__hyper_iter_has_next_block,
H5S__hyper_iter_next,
H5S__hyper_iter_next_block,
H5S__hyper_iter_get_seq_list,
H5S__hyper_iter_release,
}};
static const hsize_t H5S_hyper_zeros_g[H5S_MAX_RANK] = {
0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0};
static const hsize_t H5S_hyper_ones_g[H5S_MAX_RANK] = {
1,1,1,1, 1,1,1,1,
1,1,1,1, 1,1,1,1,
1,1,1,1, 1,1,1,1,
1,1,1,1, 1,1,1,1};
H5FL_DEFINE_STATIC(H5S_hyper_sel_t);
H5FL_DEFINE_STATIC(H5S_hyper_span_t);
H5FL_BARR_DEFINE_STATIC(H5S_hyper_span_info_t, hbounds_t, H5S_MAX_RANK * 2);
H5FL_EXTERN(H5S_sel_iter_t);
static uint64_t H5S_hyper_op_gen_g = 1;
#ifdef H5S_HYPER_DEBUG
static herr_t
H5S__hyper_print_spans_helper(FILE *f, const H5S_hyper_span_t *span, unsigned depth)
{
FUNC_ENTER_STATIC_NOERR
while(span) {
HDfprintf(f,"%s: %*sdepth=%u, span=%p, (%Hu, %Hu), next=%p\n", FUNC, depth * 2, "", depth, span, span->low, span->high, span->next);
if(span->down) {
HDfprintf(f,"%s: %*sspans=%p, count=%u, bounds[0]={%Hu, %Hu}, head=%p\n", FUNC, (depth + 1) * 2, "", span->down, span->down->count, span->down->low_bounds[0], span->down->high_bounds[0], span->down->head);
H5S__hyper_print_spans_helper(f, span->down->head, depth + 1);
}
span = span->next;
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_print_spans(FILE *f, const H5S_hyper_span_info_t *span_lst)
{
FUNC_ENTER_STATIC_NOERR
if(span_lst != NULL) {
HDfprintf(f, "%s: spans=%p, count=%u, bounds[0]={%Hu, %Hu}, head=%p\n", FUNC, span_lst, span_lst->count, span_lst->low_bounds[0], span_lst->high_bounds[0], span_lst->head);
H5S__hyper_print_spans_helper(f, span_lst->head, 0);
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__space_print_spans(FILE *f, const H5S_t *space)
{
FUNC_ENTER_STATIC_NOERR
H5S__hyper_print_spans(f, space->select.sel_info.hslab->span_lst);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_print_diminfo_helper(FILE *f, const char *field, unsigned ndims, const H5S_hyper_dim_t *dinfo)
{
unsigned u;
FUNC_ENTER_STATIC_NOERR
if(dinfo != NULL) {
HDfprintf(f, "%s: %s: start=[", FUNC, field);
for(u = 0; u < ndims; u++)
HDfprintf(f, "%Hd%s", dinfo[u].start, (u < (ndims - 1) ? ", " : "]\n"));
HDfprintf(f, "%s: %s: stride=[", FUNC, field);
for(u = 0; u < ndims; u++)
HDfprintf(f, "%Hu%s", dinfo[u].stride, (u < (ndims - 1) ? ", " : "]\n"));
HDfprintf(f, "%s: %s: count=[", FUNC, field);
for(u = 0; u < ndims; u++)
HDfprintf(f, "%Hu%s", dinfo[u].count, (u < (ndims - 1) ? ", " : "]\n"));
HDfprintf(f, "%s: %s: block=[", FUNC, field);
for(u = 0; u < ndims; u++)
HDfprintf(f, "%Hu%s", dinfo[u].block, (u < (ndims - 1) ? ", " : "]\n"));
}
else
HDfprintf(f, "%s: %s==NULL\n", FUNC, field);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_print_diminfo(FILE *f, const H5S_t *space)
{
FUNC_ENTER_STATIC_NOERR
H5S__hyper_print_diminfo_helper(f, "diminfo.opt", space->extent.rank, space->select.sel_info.hslab->diminfo.opt);
H5S__hyper_print_diminfo_helper(f, "diminfo.app", space->extent.rank, space->select.sel_info.hslab->diminfo.app);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_print_spans_dfs(FILE *f, const H5S_hyper_span_info_t *span_lst,
unsigned depth, unsigned dims)
{
H5S_hyper_span_t *actual_tail = NULL;
H5S_hyper_span_t *cur_elem;
unsigned num_elems = 0;
unsigned u, elem_idx;
FUNC_ENTER_STATIC_NOERR
cur_elem = span_lst->head;
HDassert(cur_elem);
while(cur_elem) {
actual_tail = cur_elem;
cur_elem = cur_elem->next;
num_elems++;
}
for(u = 0; u < depth; u++)
HDfprintf(f, "\t");
HDfprintf(f, "DIM[%u]: ref_count=%u, #elems=%u, head=%p, tail=%p, actual_tail=%p, matched=%t\n", depth,
span_lst->count, num_elems, span_lst->head,
span_lst->tail, actual_tail, (span_lst->tail == actual_tail));
for(u = 0; u < depth; u++)
HDfprintf(f, "\t");
HDfprintf(f, "low_bounds=[");
for(u = 0; u < dims - 1; u++)
HDfprintf(f, "%llu,", span_lst->low_bounds[u]);
HDfprintf(f, "%llu]\n", span_lst->low_bounds[dims - 1]);
for(u = 0; u < depth; u++)
HDfprintf(f, "\t");
HDfprintf(f, "high_bounds=[");
for(u = 0; u < dims - 1; u++)
HDfprintf(f, "%llu,", span_lst->high_bounds[u]);
HDfprintf(f, "%llu]\n", span_lst->high_bounds[dims - 1]);
cur_elem = span_lst->head;
elem_idx = 0;
while(cur_elem) {
for(u = 0; u < depth; u++)
HDfprintf(f, "\t");
HDfprintf(f, "ELEM[%u]: ptr=%p, low=%Hu, high=%Hu, down=%p\n",
elem_idx++, cur_elem, cur_elem->low, cur_elem->high, cur_elem->down);
if(cur_elem->down)
H5S__hyper_print_spans_dfs(f, cur_elem->down, depth + 1, dims);
cur_elem = cur_elem->next;
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
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 u;
FUNC_ENTER_STATIC_NOERR
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, " offset=[");
for(u = 0; u < dims - 1; u++)
HDfprintf(f, "%lld,", space->select.offset[u]);
HDfprintf(f, "%lld]\n", space->select.offset[dims - 1]);
HDfprintf(f, " low_bounds=[");
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
for(u = 0; u < dims - 1; u++)
HDfprintf(f, "%llu,", space->select.sel_info.hslab->diminfo.low_bounds[u]);
HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->diminfo.low_bounds[dims - 1]);
}
else {
for(u = 0; u < dims - 1; u++)
HDfprintf(f, "%llu,", space->select.sel_info.hslab->span_lst->low_bounds[u]);
HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->span_lst->low_bounds[dims - 1]);
}
HDfprintf(f, " high_bounds=[");
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
for(u = 0; u < dims - 1; u++)
HDfprintf(f, "%llu,", space->select.sel_info.hslab->diminfo.high_bounds[u]);
HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->diminfo.high_bounds[dims - 1]);
}
else {
for(u = 0; u < dims - 1; u++)
HDfprintf(f, "%llu,", space->select.sel_info.hslab->span_lst->high_bounds[u]);
HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->span_lst->high_bounds[dims - 1]);
}
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES)
H5S__hyper_print_diminfo(f, space);
if(hslab->span_lst)
H5S__hyper_print_spans_dfs(f, hslab->span_lst, 0, dims);
HDfprintf(f, "=======================\n\n");
FUNC_LEAVE_NOAPI(SUCCEED)
}
#endif
uint64_t
H5S__hyper_get_op_gen(void)
{
FUNC_ENTER_PACKAGE_NOERR
FUNC_LEAVE_NOAPI(H5S_hyper_op_gen_g++);
}
static herr_t
H5S__hyper_iter_init(const H5S_t *space, H5S_sel_iter_t *iter)
{
hsize_t *slab_size;
hsize_t acc;
unsigned slab_dim;
unsigned rank;
unsigned u;
int i;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space));
HDassert(iter);
HDassert(space->select.sel_info.hslab->unlim_dim < 0);
iter->u.hyp.iter_rank = 0;
rank = iter->rank;
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
H5S__hyper_rebuild((H5S_t *)space);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
const H5S_hyper_dim_t *tdiminfo;
const hsize_t *mem_size;
unsigned cont_dim = 0;
tdiminfo = space->select.sel_info.hslab->diminfo.opt;
mem_size = iter->dims;
if(iter->elmt_size > 0) {
for(u = (rank - 1); u > 0; u--) {
if(tdiminfo[u].count == 1 && tdiminfo[u].block == mem_size[u]) {
cont_dim++;
iter->u.hyp.flattened[u] = TRUE;
}
else
iter->u.hyp.flattened[u] = FALSE;
}
iter->u.hyp.flattened[0] = FALSE;
}
if(cont_dim > 0) {
hbool_t last_dim_flattened = TRUE;
unsigned flat_rank = rank-cont_dim;
unsigned curr_dim;
iter->u.hyp.iter_rank = flat_rank;
curr_dim = flat_rank - 1;
for(i = (int)rank - 1, acc = 1; i >= 0; i--) {
if(tdiminfo[i].block == mem_size[i] && i > 0) {
HDassert(tdiminfo[i].start == 0);
acc *= mem_size[i];
last_dim_flattened = TRUE;
}
else {
if(last_dim_flattened) {
iter->u.hyp.diminfo[curr_dim].start = tdiminfo[i].start * acc;
if(tdiminfo[i].count == 1)
iter->u.hyp.diminfo[curr_dim].stride = 1;
else
iter->u.hyp.diminfo[curr_dim].stride = tdiminfo[i].stride * acc;
iter->u.hyp.diminfo[curr_dim].count = tdiminfo[i].count;
iter->u.hyp.diminfo[curr_dim].block = tdiminfo[i].block * acc;
iter->u.hyp.size[curr_dim] = mem_size[i] * acc;
iter->u.hyp.sel_off[curr_dim] = iter->sel_off[i] * (hssize_t)acc;
last_dim_flattened = FALSE;
acc = 1;
}
else {
iter->u.hyp.diminfo[curr_dim].start = tdiminfo[i].start;
iter->u.hyp.diminfo[curr_dim].stride = tdiminfo[i].stride;
iter->u.hyp.diminfo[curr_dim].count = tdiminfo[i].count;
iter->u.hyp.diminfo[curr_dim].block = tdiminfo[i].block;
iter->u.hyp.size[curr_dim] = mem_size[i];
iter->u.hyp.sel_off[curr_dim] = iter->sel_off[i];
}
curr_dim--;
}
}
for(u = 0; u < flat_rank; u++)
iter->u.hyp.off[u] = iter->u.hyp.diminfo[u].start;
slab_dim = iter->u.hyp.iter_rank - 1;
slab_size = iter->u.hyp.size;
}
else {
HDcompile_assert(sizeof(iter->u.hyp.diminfo) == sizeof(space->select.sel_info.hslab->diminfo.opt));
H5MM_memcpy(iter->u.hyp.diminfo, tdiminfo, sizeof(iter->u.hyp.diminfo));
for(u = 0; u < rank; u++)
iter->u.hyp.off[u] = tdiminfo[u].start;
slab_dim = iter->rank - 1;
slab_size = iter->dims;
}
iter->u.hyp.diminfo_valid = TRUE;
iter->u.hyp.spans = NULL;
}
else {
H5S_hyper_span_info_t *spans;
if((iter->flags & H5S_SEL_ITER_API_CALL) &&
!(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) {
if(NULL == (iter->u.hyp.spans = H5S__hyper_copy_span(space->select.sel_info.hslab->span_lst, space->extent.rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy span tree")
}
else {
HDassert(space->select.sel_info.hslab->span_lst);
iter->u.hyp.spans = space->select.sel_info.hslab->span_lst;
iter->u.hyp.spans->count++;
}
spans = iter->u.hyp.spans;
for(u = 0; u < rank; u++) {
HDassert(spans);
HDassert(spans->head);
iter->u.hyp.span[u] = spans->head;
iter->u.hyp.off[u] = iter->u.hyp.span[u]->low;
spans = spans->head->down;
}
slab_dim = iter->rank - 1;
slab_size = iter->dims;
iter->u.hyp.diminfo_valid = FALSE;
}
for(i = (int)slab_dim, acc = iter->elmt_size; i >= 0; i--) {
iter->u.hyp.slab[i] = acc;
acc *= slab_size[i];
}
if(!iter->u.hyp.diminfo_valid) {
for(u = 0; u < rank; u++)
iter->u.hyp.loc_off[u] = ((hsize_t)((hssize_t)iter->u.hyp.off[u] + iter->sel_off[u])) * iter->u.hyp.slab[u];
}
iter->type = H5S_sel_iter_hyper;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords)
{
FUNC_ENTER_STATIC_NOERR
HDassert(iter);
HDassert(coords);
if(iter->u.hyp.diminfo_valid) {
if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
int u, v;
u = (int)iter->rank - 1;
v = (int)iter->u.hyp.iter_rank - 1;
while(u >= 0) {
if(iter->u.hyp.flattened[u]) {
int begin = u;
do {
u--;
} while(u >= 0 && iter->u.hyp.flattened[u]);
if(u < 0)
u = 0;
HDassert(v >= 0);
H5VM_array_calc(iter->u.hyp.off[v], (unsigned)((begin - u) + 1), &(iter->dims[u]), &(coords[u]));
u--;
v--;
}
else {
while(u >= 0 && !iter->u.hyp.flattened[u]) {
HDassert(v >= 0);
coords[u] = iter->u.hyp.off[v];
u--;
v--;
}
}
}
HDassert(v < 0);
}
else
H5MM_memcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank);
}
else
H5MM_memcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
{
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(iter);
HDassert(start);
HDassert(end);
if(iter->u.hyp.diminfo_valid) {
for(u = 0; u < iter->rank; u++) {
start[u] = iter->u.hyp.off[u];
end[u] = (start[u] + iter->u.hyp.diminfo[u].block) - 1;
}
}
else {
for(u = 0; u < iter->rank; u++) {
start[u] = iter->u.hyp.span[u]->low;
end[u] = iter->u.hyp.span[u]->high;
}
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static hsize_t
H5S__hyper_iter_nelmts(const H5S_sel_iter_t *iter)
{
FUNC_ENTER_STATIC_NOERR
HDassert(iter);
FUNC_LEAVE_NOAPI(iter->elmt_left)
}
static H5_ATTR_PURE htri_t
H5S__hyper_iter_has_next_block(const H5S_sel_iter_t *iter)
{
unsigned u;
htri_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(iter);
if(iter->u.hyp.diminfo_valid) {
const H5S_hyper_dim_t *tdiminfo;
const hsize_t *toff;
tdiminfo = iter->u.hyp.diminfo;
toff = iter->u.hyp.off;
for(u = 0; u < iter->rank; u++) {
if(tdiminfo[u].count == 1)
continue;
if(toff[u] != (tdiminfo[u].start + ((tdiminfo[u].count - 1) * tdiminfo[u].stride)))
HGOTO_DONE(TRUE);
}
}
else {
for(u = 0; u < iter->rank; u++)
if(iter->u.hyp.span[u]->next != NULL)
HGOTO_DONE(TRUE);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
{
unsigned ndims;
int fast_dim;
unsigned u;
FUNC_ENTER_STATIC_NOERR
if(iter->u.hyp.diminfo_valid) {
const H5S_hyper_dim_t *tdiminfo;
hsize_t iter_offset[H5S_MAX_RANK];
hsize_t iter_count[H5S_MAX_RANK];
int temp_dim;
if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank)
ndims = iter->u.hyp.iter_rank;
else
ndims = iter->rank;
fast_dim = (int)ndims - 1;
tdiminfo = iter->u.hyp.diminfo;
for(u = 0; u < ndims; u++) {
if(tdiminfo[u].count == 1) {
iter_offset[u] = iter->u.hyp.off[u] - tdiminfo[u].start;
iter_count[u] = 0;
}
else {
iter_offset[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) % tdiminfo[u].stride;
iter_count[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) / tdiminfo[u].stride;
}
}
while(nelem > 0) {
temp_dim = fast_dim;
while(temp_dim >= 0) {
if(temp_dim == fast_dim) {
size_t actual_elem;
hsize_t block_elem;
block_elem = tdiminfo[temp_dim].block - iter_offset[temp_dim];
actual_elem = (size_t)MIN(nelem, block_elem);
iter_offset[temp_dim] += actual_elem;
nelem -= actual_elem;
}
else
iter_offset[temp_dim]++;
if(iter_offset[temp_dim] < tdiminfo[temp_dim].block)
break;
else {
iter_offset[temp_dim] = 0;
iter_count[temp_dim]++;
if(iter_count[temp_dim] < tdiminfo[temp_dim].count)
break;
else
iter_count[temp_dim] = 0;
}
temp_dim--;
}
}
for(u = 0; u < ndims; u++)
iter->u.hyp.off[u] = tdiminfo[u].start + (tdiminfo[u].stride * iter_count[u]) + iter_offset[u];
}
else {
H5S_hyper_span_t *curr_span;
H5S_hyper_span_t **ispan;
hsize_t *abs_arr;
int curr_dim;
ndims = iter->rank;
fast_dim = (int)ndims - 1;
abs_arr = iter->u.hyp.off;
ispan = iter->u.hyp.span;
while(nelem > 0) {
curr_dim = fast_dim;
while(curr_dim >= 0) {
curr_span = ispan[curr_dim];
if(curr_dim == fast_dim) {
size_t actual_elem;
hsize_t span_elem;
span_elem = (curr_span->high - abs_arr[curr_dim]) + 1;
actual_elem = (size_t)MIN(nelem, span_elem);
abs_arr[curr_dim] += actual_elem;
nelem -= actual_elem;
}
else
abs_arr[curr_dim]++;
if(abs_arr[curr_dim] <= curr_span->high)
break;
else {
curr_span = curr_span->next;
if(curr_span != NULL) {
ispan[curr_dim] = curr_span;
abs_arr[curr_dim] = curr_span->low;
break;
}
else
curr_dim--;
}
}
if(curr_dim >= 0) {
while(curr_dim < fast_dim) {
HDassert(curr_span);
HDassert(curr_span->down);
HDassert(curr_span->down->head);
curr_dim++;
ispan[curr_dim] = curr_span->down->head;
curr_span = curr_span->down->head;
abs_arr[curr_dim] = curr_span->low;
}
HDassert(curr_span == ispan[fast_dim]);
}
}
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_iter_next_block(H5S_sel_iter_t *iter)
{
unsigned ndims;
int fast_dim;
unsigned u;
FUNC_ENTER_STATIC_NOERR
if(iter->u.hyp.diminfo_valid) {
const H5S_hyper_dim_t *tdiminfo;
hsize_t iter_offset[H5S_MAX_RANK];
hsize_t iter_count[H5S_MAX_RANK];
int temp_dim;
if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank)
ndims = iter->u.hyp.iter_rank;
else
ndims = iter->rank;
fast_dim = (int)ndims - 1;
tdiminfo = iter->u.hyp.diminfo;
for(u = 0; u < ndims; u++) {
if(tdiminfo[u].count == 1) {
iter_offset[u] = iter->u.hyp.off[u] - tdiminfo[u].start;
iter_count[u] = 0;
}
else {
iter_offset[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) % tdiminfo[u].stride;
iter_count[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) / tdiminfo[u].stride;
}
}
temp_dim = fast_dim;
while(temp_dim >= 0) {
if(temp_dim == fast_dim)
iter_offset[temp_dim] += tdiminfo[temp_dim].block;
else
iter_offset[temp_dim]++;
if(iter_offset[temp_dim] < tdiminfo[temp_dim].block)
break;
else {
iter_offset[temp_dim] = 0;
iter_count[temp_dim]++;
if(iter_count[temp_dim] < tdiminfo[temp_dim].count)
break;
else
iter_count[temp_dim] = 0;
}
temp_dim--;
}
for(u = 0; u < ndims; u++)
iter->u.hyp.off[u] = tdiminfo[u].start + (tdiminfo[u].stride * iter_count[u]) + iter_offset[u];
}
else {
H5S_hyper_span_t *curr_span;
H5S_hyper_span_t **ispan;
hsize_t *abs_arr;
int curr_dim;
ndims = iter->rank;
fast_dim = (int)ndims - 1;
abs_arr = iter->u.hyp.off;
ispan = iter->u.hyp.span;
curr_dim = fast_dim;
while(curr_dim >= 0) {
curr_span = ispan[curr_dim];
if(curr_dim == fast_dim)
abs_arr[curr_dim] = curr_span->high + 1;
else
abs_arr[curr_dim]++;
if(abs_arr[curr_dim] <= curr_span->high)
break;
else {
curr_span = curr_span->next;
if(curr_span != NULL) {
ispan[curr_dim] = curr_span;
abs_arr[curr_dim] = curr_span->low;
break;
}
else
curr_dim--;
}
}
if(curr_dim >= 0) {
while(curr_dim < fast_dim) {
HDassert(curr_span);
HDassert(curr_span->down);
HDassert(curr_span->down->head);
curr_dim++;
ispan[curr_dim] = curr_span->down->head;
curr_span = curr_span->down->head;
abs_arr[curr_dim] = curr_span->low;
}
HDassert(curr_span == ispan[fast_dim]);
}
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_iter_get_seq_list_gen(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem,
size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
{
H5S_hyper_span_t *curr_span;
H5S_hyper_span_t **ispan;
hsize_t *slab;
hsize_t loc_off;
hsize_t last_span_end = 0;
hsize_t *abs_arr;
hsize_t *loc_arr;
const hssize_t *sel_off;
size_t span_elmts = 0;
size_t span_size = 0;
size_t io_left;
size_t io_elmts_left;
size_t io_used;
size_t curr_seq = 0;
size_t elem_size;
unsigned ndims;
unsigned fast_dim;
int curr_dim;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(iter);
HDassert(maxseq > 0);
HDassert(maxelem > 0);
HDassert(nseq);
HDassert(nelem);
HDassert(off);
HDassert(len);
ndims = iter->rank;
fast_dim = (ndims - 1);
curr_span = iter->u.hyp.span[fast_dim];
abs_arr = iter->u.hyp.off;
loc_arr = iter->u.hyp.loc_off;
slab = iter->u.hyp.slab;
sel_off = iter->sel_off;
ispan = iter->u.hyp.span;
elem_size = iter->elmt_size;
H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
io_elmts_left = io_left = MIN(maxelem, (size_t)iter->elmt_left);
for(u = 0, loc_off = 0; u < ndims; u++)
loc_off += loc_arr[u];
if(abs_arr[fast_dim] != curr_span->low) {
H5_CHECKED_ASSIGN(span_elmts, size_t, ((curr_span->high - abs_arr[fast_dim]) + 1), hsize_t);
if(span_elmts > io_elmts_left)
span_elmts = io_elmts_left;
span_size = span_elmts * elem_size;
off[curr_seq] = loc_off;
len[curr_seq] = span_size;
curr_seq++;
last_span_end = loc_off + span_size;
io_elmts_left -= span_elmts;
if(io_elmts_left > 0) {
curr_span = curr_span->next;
if(NULL != curr_span) {
loc_off += (curr_span->low - abs_arr[fast_dim]) * elem_size;
abs_arr[fast_dim] = curr_span->low;
loc_arr[fast_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[fast_dim])) * slab[fast_dim];
ispan[fast_dim] = curr_span;
}
}
else {
abs_arr[fast_dim] += span_elmts;
if(abs_arr[fast_dim] <= curr_span->high) {
HDassert(ispan[fast_dim] == curr_span);
loc_arr[fast_dim] += span_size;
}
else {
curr_span = curr_span->next;
if(NULL != curr_span) {
abs_arr[fast_dim] = curr_span->low;
loc_arr[fast_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[fast_dim])) * slab[fast_dim];
ispan[fast_dim] = curr_span;
}
}
}
if(NULL == curr_span) {
curr_dim = (int)(fast_dim - 1);
while(curr_dim >= 0) {
curr_span = ispan[curr_dim];
abs_arr[curr_dim]++;
if(abs_arr[curr_dim] <= curr_span->high) {
loc_arr[curr_dim] += slab[curr_dim];
break;
}
else {
curr_span = curr_span->next;
if(NULL != curr_span) {
ispan[curr_dim] = curr_span;
abs_arr[curr_dim] = curr_span->low;
loc_arr[curr_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[curr_dim])) * slab[curr_dim];
break;
}
else
curr_dim--;
}
}
if(curr_dim >= 0) {
while((unsigned)curr_dim < fast_dim) {
HDassert(curr_span);
HDassert(curr_span->down);
HDassert(curr_span->down->head);
curr_dim++;
ispan[curr_dim] = curr_span->down->head;
curr_span = curr_span->down->head;
abs_arr[curr_dim] = curr_span->low;
loc_arr[curr_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[curr_dim])) * slab[curr_dim];
}
HDassert(curr_span == ispan[fast_dim]);
for(u = 0, loc_off = 0; u < ndims; u++)
loc_off += loc_arr[u];
}
else
HDassert(io_elmts_left == 0);
}
}
while(io_elmts_left > 0 && curr_seq < maxseq) {
H5S_hyper_span_t *prev_span;
HDassert(curr_span);
prev_span = curr_span;
while(curr_span != NULL) {
hsize_t nelmts;
loc_off += (curr_span->low - prev_span->low) * elem_size;
nelmts = (curr_span->high - curr_span->low) + 1;
H5_CHECKED_ASSIGN(span_elmts, size_t, nelmts, hsize_t);
if(span_elmts >= io_elmts_left) {
span_elmts = io_elmts_left;
span_size = span_elmts * elem_size;
io_elmts_left = 0;
if(curr_seq > 0 && last_span_end == loc_off)
len[curr_seq - 1] += span_size;
else {
off[curr_seq] = loc_off;
len[curr_seq] = span_size;
curr_seq++;
}
break;
}
else {
span_size = span_elmts * elem_size;
io_elmts_left -= span_elmts;
if(curr_seq > 0 && last_span_end == loc_off)
len[curr_seq - 1] += span_size;
else {
off[curr_seq] = loc_off;
len[curr_seq] = span_size;
curr_seq++;
}
if(curr_seq >= maxseq)
break;
}
last_span_end = loc_off + span_size;
prev_span = curr_span;
curr_span = curr_span->next;
}
if(io_elmts_left == 0 || curr_seq >= maxseq) {
HDassert(curr_span);
abs_arr[fast_dim] = curr_span->low + span_elmts;
if(abs_arr[fast_dim] <= curr_span->high) {
ispan[fast_dim] = curr_span;
loc_arr[fast_dim] = ((hsize_t)((hssize_t)curr_span->low + (hssize_t)span_elmts + sel_off[fast_dim])) * slab[fast_dim];
break;
}
else {
curr_span = curr_span->next;
if(curr_span != NULL) {
abs_arr[fast_dim] = curr_span->low;
loc_arr[fast_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[fast_dim])) * slab[fast_dim];
ispan[fast_dim] = curr_span;
break;
}
}
}
curr_dim = (int)(fast_dim - 1);
while(curr_dim >= 0) {
curr_span = ispan[curr_dim];
abs_arr[curr_dim]++;
if(abs_arr[curr_dim] <= curr_span->high) {
loc_arr[curr_dim] += slab[curr_dim];
break;
}
else {
curr_span = curr_span->next;
if(curr_span != NULL) {
ispan[curr_dim] = curr_span;
abs_arr[curr_dim] = curr_span->low;
loc_arr[curr_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[curr_dim])) * slab[curr_dim];
break;
}
else
curr_dim--;
}
}
if(curr_dim < 0) {
HDassert(io_elmts_left == 0);
break;
}
else {
while((unsigned)curr_dim < fast_dim) {
HDassert(curr_span);
HDassert(curr_span->down);
HDassert(curr_span->down->head);
curr_dim++;
ispan[curr_dim] = curr_span->down->head;
curr_span = curr_span->down->head;
abs_arr[curr_dim] = curr_span->low;
loc_arr[curr_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[curr_dim])) * slab[curr_dim];
}
HDassert(curr_span == ispan[fast_dim]);
}
for(u = 0, loc_off = 0; u < ndims; u++)
loc_off += loc_arr[u];
}
io_used = io_left - io_elmts_left;
iter->elmt_left -= io_used;
*nseq = curr_seq;
*nelem = io_used;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_iter_get_seq_list_opt(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem,
size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
{
hsize_t *mem_size;
hsize_t *slab;
const hssize_t *sel_off;
hsize_t offset[H5S_MAX_RANK];
hsize_t tmp_count[H5S_MAX_RANK];
hsize_t tmp_block[H5S_MAX_RANK];
hsize_t wrap[H5S_MAX_RANK];
hsize_t skip[H5S_MAX_RANK];
const H5S_hyper_dim_t *tdiminfo;
hsize_t fast_dim_start,
fast_dim_stride,
fast_dim_block,
fast_dim_offset;
size_t fast_dim_buf_off;
size_t fast_dim_count;
size_t tot_blk_count;
size_t act_blk_count;
size_t total_rows;
size_t curr_rows;
unsigned fast_dim;
unsigned ndims;
int temp_dim;
hsize_t loc;
size_t curr_seq = 0;
size_t actual_elem;
size_t actual_bytes;
size_t io_left;
size_t start_io_left;
size_t elem_size;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(iter);
HDassert(maxseq > 0);
HDassert(maxelem > 0);
HDassert(nseq);
HDassert(nelem);
HDassert(off);
HDassert(len);
tdiminfo = iter->u.hyp.diminfo;
if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
ndims = iter->u.hyp.iter_rank;
sel_off = iter->u.hyp.sel_off;
mem_size = iter->u.hyp.size;
}
else {
ndims = iter->rank;
sel_off = iter->sel_off;
mem_size = iter->dims;
}
fast_dim = ndims - 1;
elem_size = iter->elmt_size;
slab = iter->u.hyp.slab;
H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
io_left = MIN((size_t)iter->elmt_left, maxelem);
HDassert(!((iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start) % tdiminfo[fast_dim].stride != 0 ||
((iter->u.hyp.off[fast_dim] != tdiminfo[fast_dim].start) && tdiminfo[fast_dim].count == 1)));
start_io_left = io_left;
for(u = 0; u < ndims; u++)
offset[u] = (hsize_t)((hssize_t)iter->u.hyp.off[u] + sel_off[u]);
for(u = 0; u < ndims; u++) {
if(tdiminfo[u].count == 1) {
tmp_count[u] = 0;
tmp_block[u] = iter->u.hyp.off[u] - tdiminfo[u].start;
}
else {
tmp_count[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) / tdiminfo[u].stride;
tmp_block[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) % tdiminfo[u].stride;
}
}
for(u = 0, loc = 0; u < ndims; u++)
loc += offset[u] * slab[u];
H5_CHECKED_ASSIGN(actual_elem, size_t, tdiminfo[fast_dim].block, hsize_t);
actual_bytes = actual_elem * elem_size;
fast_dim_start = tdiminfo[fast_dim].start;
fast_dim_stride = tdiminfo[fast_dim].stride;
fast_dim_block = tdiminfo[fast_dim].block;
H5_CHECKED_ASSIGN(fast_dim_buf_off, size_t, slab[fast_dim] * fast_dim_stride, hsize_t);
fast_dim_offset = (hsize_t)((hssize_t)fast_dim_start + sel_off[fast_dim]);
H5_CHECK_OVERFLOW(io_left / fast_dim_block, hsize_t, size_t);
tot_blk_count = (size_t)(io_left / fast_dim_block);
tot_blk_count = MIN(tot_blk_count, (maxseq - curr_seq));
for(u = 0; u < ndims; u++)
wrap[u] = (mem_size[u] - (tdiminfo[u].stride * tdiminfo[u].count)) * slab[u];
for(u = 0; u < ndims; u++)
skip[u] = (tdiminfo[u].stride - tdiminfo[u].block) * slab[u];
if(tmp_count[fast_dim] > 0) {
H5_CHECKED_ASSIGN(fast_dim_count, size_t, tdiminfo[fast_dim].count - tmp_count[fast_dim], hsize_t);
fast_dim_count = MIN(fast_dim_count, tot_blk_count);
act_blk_count = fast_dim_count;
while(fast_dim_count > 0) {
off[curr_seq] = loc;
len[curr_seq] = actual_bytes;
curr_seq++;
loc += fast_dim_buf_off;
fast_dim_count--;
}
io_left -= actual_elem * act_blk_count;
tot_blk_count -= act_blk_count;
tmp_count[fast_dim] += act_blk_count;
if(tmp_count[fast_dim] >= tdiminfo[fast_dim].count) {
loc += wrap[fast_dim];
offset[fast_dim] = fast_dim_offset;
tmp_count[fast_dim] = 0;
temp_dim = (int)fast_dim - 1;
while(temp_dim >= 0) {
offset[temp_dim]++;
tmp_block[temp_dim]++;
if(tmp_block[temp_dim] < tdiminfo[temp_dim].block)
break;
else {
offset[temp_dim] += (tdiminfo[temp_dim].stride - tdiminfo[temp_dim].block);
loc += skip[temp_dim];
tmp_block[temp_dim] = 0;
tmp_count[temp_dim]++;
if(tmp_count[temp_dim] < tdiminfo[temp_dim].count)
break;
else {
offset[temp_dim] = (hsize_t)((hssize_t)tdiminfo[temp_dim].start + sel_off[temp_dim]);
loc += wrap[temp_dim];
tmp_count[temp_dim] = 0;
tmp_block[temp_dim] = 0;
}
}
temp_dim--;
}
}
else {
offset[fast_dim] += (fast_dim_stride * act_blk_count);
}
}
H5_CHECK_OVERFLOW(tot_blk_count / tdiminfo[fast_dim].count, hsize_t, size_t);
curr_rows = total_rows = (size_t)(tot_blk_count / tdiminfo[fast_dim].count);
H5_CHECKED_ASSIGN(fast_dim_count, size_t, tdiminfo[fast_dim].count, hsize_t);
while(curr_rows > 0) {
#define DUFF_GUTS \
\
off[curr_seq] = loc; \
len[curr_seq] = actual_bytes; \
\
\
curr_seq++; \
\
\
loc += fast_dim_buf_off;
#ifdef NO_DUFFS_DEVICE
while(fast_dim_count > 0) {
DUFF_GUTS
fast_dim_count--;
}
#else
{
size_t duffs_index;
duffs_index = (fast_dim_count + 7) / 8;
switch (fast_dim_count % 8) {
default:
HDassert(0 && "This Should never be executed!");
break;
case 0:
do
{
DUFF_GUTS
H5_ATTR_FALLTHROUGH
case 7:
DUFF_GUTS
H5_ATTR_FALLTHROUGH
case 6:
DUFF_GUTS
H5_ATTR_FALLTHROUGH
case 5:
DUFF_GUTS
H5_ATTR_FALLTHROUGH
case 4:
DUFF_GUTS
H5_ATTR_FALLTHROUGH
case 3:
DUFF_GUTS
H5_ATTR_FALLTHROUGH
case 2:
DUFF_GUTS
H5_ATTR_FALLTHROUGH
case 1:
DUFF_GUTS
} while (--duffs_index > 0);
}
}
#endif
#undef DUFF_GUTS
loc += wrap[fast_dim];
temp_dim = (int)fast_dim - 1;
while(temp_dim >= 0) {
offset[temp_dim]++;
tmp_block[temp_dim]++;
if(tmp_block[temp_dim] < tdiminfo[temp_dim].block)
break;
else {
offset[temp_dim] += (tdiminfo[temp_dim].stride - tdiminfo[temp_dim].block);
loc += skip[temp_dim];
tmp_block[temp_dim] = 0;
tmp_count[temp_dim]++;
if(tmp_count[temp_dim] < tdiminfo[temp_dim].count)
break;
else {
offset[temp_dim] = (hsize_t)((hssize_t)tdiminfo[temp_dim].start + sel_off[temp_dim]);
loc += wrap[temp_dim];
tmp_count[temp_dim] = 0;
tmp_block[temp_dim] = 0;
}
}
temp_dim--;
}
curr_rows--;
}
H5_CHECK_OVERFLOW(actual_elem * (total_rows * tdiminfo[fast_dim].count), hsize_t, size_t);
io_left -= (size_t)(actual_elem * (total_rows * tdiminfo[fast_dim].count));
H5_CHECK_OVERFLOW((total_rows * tdiminfo[fast_dim].count), hsize_t, size_t);
tot_blk_count -= (size_t)(total_rows * tdiminfo[fast_dim].count);
if(io_left > 0 && curr_seq < maxseq) {
fast_dim_count = tot_blk_count;
while(fast_dim_count > 0) {
off[curr_seq] = loc;
len[curr_seq] = actual_bytes;
curr_seq++;
loc += fast_dim_buf_off;
fast_dim_count--;
}
io_left -= actual_elem * tot_blk_count;
offset[fast_dim] += (fast_dim_stride * tot_blk_count);
if(io_left > 0 && curr_seq < maxseq) {
actual_elem = io_left;
actual_bytes = actual_elem * elem_size;
off[curr_seq] = loc;
len[curr_seq] = actual_bytes;
curr_seq++;
io_left -= actual_elem;
offset[fast_dim] += actual_elem;
}
HDassert(io_left == 0 || curr_seq == maxseq);
}
for(u = 0; u < ndims; u++)
iter->u.hyp.off[u] = (hsize_t)((hssize_t)offset[u] - sel_off[u]);
iter->elmt_left -= (start_io_left - io_left);
*nseq += curr_seq;
*nelem += start_io_left - io_left;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_iter_get_seq_list_single(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem,
size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
{
const H5S_hyper_dim_t *tdiminfo;
const hssize_t *sel_off;
hsize_t *mem_size;
hsize_t base_offset[H5S_MAX_RANK];
hsize_t offset[H5S_MAX_RANK];
hsize_t *slab;
hsize_t fast_dim_block;
hsize_t loc;
size_t tot_blk_count;
size_t elem_size;
size_t io_left;
size_t actual_elem;
unsigned ndims;
unsigned fast_dim;
unsigned skip_dim;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(iter);
HDassert(maxseq > 0);
HDassert(maxelem > 0);
HDassert(nseq);
HDassert(nelem);
HDassert(off);
HDassert(len);
tdiminfo = iter->u.hyp.diminfo;
if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
ndims = iter->u.hyp.iter_rank;
sel_off = iter->u.hyp.sel_off;
mem_size = iter->u.hyp.size;
}
else {
ndims = iter->rank;
sel_off = iter->sel_off;
mem_size = iter->dims;
}
fast_dim = ndims - 1;
elem_size = iter->elmt_size;
slab = iter->u.hyp.slab;
for(u = 0; u < ndims; u++)
base_offset[u] = (hsize_t)((hssize_t)tdiminfo[u].start + sel_off[u]);
for(u = 0; u < ndims; u++)
offset[u] = (hsize_t)((hssize_t)iter->u.hyp.off[u] + sel_off[u]);
for(u = 0, loc = 0; u < ndims; u++)
loc += offset[u] * slab[u];
fast_dim_block = tdiminfo[fast_dim].block;
H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
io_left = MIN((size_t)iter->elmt_left, maxelem);
H5_CHECK_OVERFLOW(io_left / fast_dim_block, hsize_t, size_t);
tot_blk_count = (size_t)(io_left / fast_dim_block);
tot_blk_count = MIN(tot_blk_count, maxseq);
H5_CHECKED_ASSIGN(actual_elem, size_t, fast_dim_block, hsize_t);
if(tot_blk_count > 0) {
size_t actual_bytes;
actual_bytes = actual_elem * elem_size;
if(0 == fast_dim) {
HDassert(1 == tot_blk_count);
HDassert(io_left == actual_elem);
*off++ = loc;
*len++ = actual_bytes;
}
else {
hsize_t skip_slab;
size_t blk_count;
int i;
skip_dim = fast_dim;
for(i = (int)(fast_dim - 1); i >= 0; i--)
if(tdiminfo[i].block > 1) {
skip_dim = (unsigned)i;
break;
}
skip_slab = slab[skip_dim];
if(0 == skip_dim) {
blk_count = tot_blk_count;
while(blk_count > 0) {
*off++ = loc;
*len++ = actual_bytes;
loc += skip_slab;
blk_count--;
}
offset[skip_dim] += tot_blk_count;
}
else {
hsize_t tmp_block[H5S_MAX_RANK];
hsize_t skip[H5S_MAX_RANK];
int temp_dim;
for(u = 0; u < ndims; u++)
tmp_block[u] = iter->u.hyp.off[u] - tdiminfo[u].start;
for(u = 0; u < ndims; u++)
skip[u] = (mem_size[u] - tdiminfo[u].block) * slab[u];
blk_count = tot_blk_count;
while(blk_count > 0) {
*off++ = loc;
*len++ = actual_bytes;
temp_dim = (int)skip_dim;
loc += skip_slab;
while(temp_dim >= 0) {
offset[temp_dim]++;
tmp_block[temp_dim]++;
if(tmp_block[temp_dim] < tdiminfo[temp_dim].block)
break;
else {
offset[temp_dim] = base_offset[temp_dim];
loc += skip[temp_dim];
tmp_block[temp_dim] = 0;
}
temp_dim--;
}
blk_count--;
}
}
}
iter->elmt_left -= tot_blk_count * actual_elem;
if(iter->elmt_left > 0) {
for(u = 0; u < ndims; u++)
iter->u.hyp.off[u] = (hsize_t)((hssize_t)offset[u] - sel_off[u]);
}
*nseq += tot_blk_count;
*nelem += tot_blk_count * actual_elem;
}
if(io_left > (tot_blk_count * actual_elem) && tot_blk_count < maxseq) {
size_t elmt_remainder;
elmt_remainder = io_left - (tot_blk_count * actual_elem);
HDassert(elmt_remainder < fast_dim_block);
HDassert(elmt_remainder > 0);
*off++ = loc;
*len++ = elmt_remainder * elem_size;
iter->u.hyp.off[fast_dim] += (hsize_t)elmt_remainder;
iter->elmt_left -= elmt_remainder;
(*nseq)++;
*nelem += elmt_remainder;
}
HDassert(*nseq > 0);
HDassert(*nelem > 0);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq,
size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
{
herr_t ret_value = FAIL;
FUNC_ENTER_STATIC_NOERR
HDassert(iter);
HDassert(iter->elmt_left > 0);
HDassert(maxseq > 0);
HDassert(maxelem > 0);
HDassert(nseq);
HDassert(nelem);
HDassert(off);
HDassert(len);
if(iter->u.hyp.diminfo_valid) {
const H5S_hyper_dim_t *tdiminfo;
const hssize_t *sel_off;
unsigned ndims;
unsigned fast_dim;
hbool_t single_block;
unsigned u;
tdiminfo = iter->u.hyp.diminfo;
if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
ndims = iter->u.hyp.iter_rank;
sel_off = iter->u.hyp.sel_off;
}
else {
ndims = iter->rank;
sel_off = iter->sel_off;
}
fast_dim = ndims - 1;
if((iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start) % tdiminfo[fast_dim].stride != 0 ||
((iter->u.hyp.off[fast_dim] != tdiminfo[fast_dim].start) && tdiminfo[fast_dim].count == 1)) {
hsize_t *slab;
hsize_t loc;
size_t leftover;
size_t actual_elem;
size_t elem_size;
if(tdiminfo[fast_dim].count == 1) {
H5_CHECKED_ASSIGN(leftover, size_t, tdiminfo[fast_dim].block - (iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start), hsize_t);
}
else {
H5_CHECKED_ASSIGN(leftover, size_t, tdiminfo[fast_dim].block - ((iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start) % tdiminfo[fast_dim].stride), hsize_t);
}
actual_elem = MIN3(leftover, (size_t)iter->elmt_left, maxelem);
elem_size = iter->elmt_size;
slab = iter->u.hyp.slab;
for(u = 0, loc = 0; u < ndims; u++)
loc += ((hsize_t)((hssize_t)iter->u.hyp.off[u] + sel_off[u])) * slab[u];
off[0] = loc;
H5_CHECKED_ASSIGN(len[0], size_t, actual_elem * elem_size, hsize_t);
off++;
len++;
H5S__hyper_iter_next(iter, actual_elem);
iter->elmt_left -= actual_elem;
maxelem -= actual_elem;
maxseq--;
*nseq = 1;
*nelem = actual_elem;
if(0 == iter->elmt_left || 0 == maxelem || 0 == maxseq)
return(SUCCEED);
}
else {
*nseq = 0;
*nelem = 0;
}
single_block = TRUE;
for(u = 0; u < ndims; u++)
if(1 != tdiminfo[u].count) {
single_block = FALSE;
break;
}
if(single_block)
ret_value = H5S__hyper_iter_get_seq_list_single(iter, maxseq, maxelem, nseq, nelem, off, len);
else
ret_value = H5S__hyper_iter_get_seq_list_opt(iter, maxseq, maxelem, nseq, nelem, off, len);
}
else
ret_value = H5S__hyper_iter_get_seq_list_gen(iter, maxseq, maxelem, nseq, nelem, off, len);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_iter_release(H5S_sel_iter_t *iter)
{
FUNC_ENTER_STATIC_NOERR
HDassert(iter);
if(iter->u.hyp.spans != NULL)
H5S__hyper_free_span_info(iter->u.hyp.spans);
FUNC_LEAVE_NOAPI(SUCCEED)
}
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)
{
H5S_hyper_span_t *ret_value = NULL;
FUNC_ENTER_STATIC
if(NULL == (ret_value = H5FL_MALLOC(H5S_hyper_span_t)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
ret_value->low = low;
ret_value->high = high;
ret_value->down = down;
ret_value->next = next;
if(ret_value->down)
ret_value->down->count++;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5S_hyper_span_info_t *
H5S__hyper_new_span_info(unsigned rank)
{
H5S_hyper_span_info_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(rank > 0);
HDassert(rank <= H5S_MAX_RANK);
if(NULL == (ret_value = (H5S_hyper_span_info_t *)H5FL_ARR_CALLOC(hbounds_t, rank * 2)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span info")
ret_value->low_bounds = ret_value->bounds;
ret_value->high_bounds = &ret_value->bounds[rank];
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5S_hyper_span_info_t *
H5S__hyper_copy_span_helper(H5S_hyper_span_info_t *spans, unsigned rank,
unsigned op_info_i, uint64_t op_gen)
{
H5S_hyper_span_t *span;
H5S_hyper_span_t *new_span;
H5S_hyper_span_t *prev_span;
H5S_hyper_span_info_t *new_down;
H5S_hyper_span_info_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(spans);
if(spans->op_info[op_info_i].op_gen == op_gen) {
ret_value = spans->op_info[op_info_i].u.copied;
ret_value->count++;
}
else {
if(NULL == (ret_value = H5S__hyper_new_span_info(rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span info")
H5MM_memcpy(ret_value->low_bounds, spans->low_bounds, rank * sizeof(hsize_t));
H5MM_memcpy(ret_value->high_bounds, spans->high_bounds, rank * sizeof(hsize_t));
ret_value->count = 1;
spans->op_info[op_info_i].op_gen = op_gen;
spans->op_info[op_info_i].u.copied = ret_value;
span = spans->head;
prev_span = NULL;
while(span != NULL) {
if(NULL == (new_span = H5S__hyper_new_span(span->low, span->high, NULL, NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
if(NULL == prev_span)
ret_value->head = new_span;
else
prev_span->next = new_span;
if(span->down != NULL) {
if(NULL == (new_down = H5S__hyper_copy_span_helper(span->down, rank - 1, op_info_i, op_gen)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy hyperslab spans")
new_span->down = new_down;
}
prev_span = new_span;
span = span->next;
}
ret_value->tail = prev_span;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5S_hyper_span_info_t *
H5S__hyper_copy_span(H5S_hyper_span_info_t *spans, unsigned rank)
{
uint64_t op_gen;
H5S_hyper_span_info_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(spans);
op_gen = H5S__hyper_get_op_gen();
if(NULL == (ret_value = H5S__hyper_copy_span_helper(spans, rank, 0, op_gen)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy hyperslab span tree")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5_ATTR_PURE hbool_t
H5S__hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1, const H5S_hyper_span_info_t *span_info2)
{
hbool_t ret_value = TRUE;
FUNC_ENTER_STATIC_NOERR
if(span_info1 != span_info2) {
if(span_info1 == NULL || span_info2 == NULL)
HGOTO_DONE(FALSE)
else {
if(span_info1->low_bounds[0] != span_info2->low_bounds[0])
HGOTO_DONE(FALSE)
else if(span_info1->high_bounds[0] != span_info2->high_bounds[0])
HGOTO_DONE(FALSE)
else {
const H5S_hyper_span_t *span1;
const H5S_hyper_span_t *span2;
span1 = span_info1->head;
span2 = span_info2->head;
HDassert(span1);
HDassert(span2);
while(1) {
if(span1 == NULL && span2 == NULL)
HGOTO_DONE(TRUE)
else {
if(span1 == NULL || span2 == NULL)
HGOTO_DONE(FALSE)
else {
if(span1->low != span2->low || span1->high != span2->high)
HGOTO_DONE(FALSE)
else {
if(span1->down != NULL || span2->down != NULL) {
if(!H5S__hyper_cmp_spans(span1->down, span2->down))
HGOTO_DONE(FALSE)
else {
}
}
else {
}
}
}
}
span1 = span1->next;
span2 = span2->next;
}
}
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void
H5S__hyper_free_span_info(H5S_hyper_span_info_t *span_info)
{
FUNC_ENTER_STATIC_NOERR
HDassert(span_info);
span_info->count--;
if(span_info->count == 0) {
H5S_hyper_span_t *span;
span = span_info->head;
while(span != NULL) {
H5S_hyper_span_t *next_span;
next_span = span->next;
H5S__hyper_free_span(span);
span = next_span;
}
span_info = (H5S_hyper_span_info_t *)H5FL_ARR_FREE(hbounds_t, span_info);
}
FUNC_LEAVE_NOAPI_VOID
}
static void
H5S__hyper_free_span(H5S_hyper_span_t *span)
{
FUNC_ENTER_STATIC_NOERR
HDassert(span);
if(span->down != NULL)
H5S__hyper_free_span_info(span->down);
span = H5FL_FREE(H5S_hyper_span_t, span);
FUNC_LEAVE_NOAPI_VOID
}
static herr_t
H5S__hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection)
{
H5S_hyper_sel_t *dst_hslab;
const H5S_hyper_sel_t *src_hslab;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(src);
HDassert(dst);
if(NULL == (dst->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info")
dst_hslab = dst->select.sel_info.hslab;
src_hslab = src->select.sel_info.hslab;
dst_hslab->diminfo_valid = src_hslab->diminfo_valid;
if(src_hslab->diminfo_valid == H5S_DIMINFO_VALID_YES)
H5MM_memcpy(&dst_hslab->diminfo, &src_hslab->diminfo, sizeof(H5S_hyper_diminfo_t));
if(src->select.sel_info.hslab->span_lst != NULL) {
if(share_selection) {
dst->select.sel_info.hslab->span_lst = src->select.sel_info.hslab->span_lst;
dst->select.sel_info.hslab->span_lst->count++;
}
else
dst->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(src->select.sel_info.hslab->span_lst, src->extent.rank);
}
else
dst->select.sel_info.hslab->span_lst = NULL;
dst_hslab->unlim_dim = src_hslab->unlim_dim;
dst_hslab->num_elem_non_unlim = src_hslab->num_elem_non_unlim;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5S__hyper_is_valid(const H5S_t *space)
{
const hsize_t *low_bounds, *high_bounds;
unsigned u;
htri_t ret_value = TRUE;
FUNC_ENTER_STATIC_NOERR
HDassert(space);
if(space->select.sel_info.hslab->unlim_dim >= 0)
HGOTO_DONE(FALSE)
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
low_bounds = space->select.sel_info.hslab->diminfo.low_bounds;
high_bounds = space->select.sel_info.hslab->diminfo.high_bounds;
}
else {
low_bounds = space->select.sel_info.hslab->span_lst->low_bounds;
high_bounds = space->select.sel_info.hslab->span_lst->high_bounds;
}
for(u = 0; u < space->extent.rank; u++) {
if(((hssize_t)low_bounds[u] + space->select.offset[u]) < 0)
HGOTO_DONE(FALSE)
if((high_bounds[u] + (hsize_t)space->select.offset[u]) >= space->extent.size[u])
HGOTO_DONE(FALSE)
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static hsize_t
H5S__hyper_span_nblocks_helper(H5S_hyper_span_info_t *spans, unsigned op_info_i,
uint64_t op_gen)
{
hsize_t ret_value = 0;
FUNC_ENTER_STATIC_NOERR
HDassert(spans);
if(spans->op_info[op_info_i].op_gen == op_gen)
ret_value = spans->op_info[op_info_i].u.nblocks;
else {
H5S_hyper_span_t *span;
span = spans->head;
if(span->down) {
while(span) {
ret_value += H5S__hyper_span_nblocks_helper(span->down, op_info_i, op_gen);
span = span->next;
}
}
else {
while(span) {
ret_value++;
span = span->next;
}
}
spans->op_info[op_info_i].op_gen = op_gen;
spans->op_info[op_info_i].u.nblocks = ret_value;
}
FUNC_LEAVE_NOAPI(ret_value)
}
static hsize_t
H5S__hyper_span_nblocks(H5S_hyper_span_info_t *spans)
{
hsize_t ret_value = 0;
FUNC_ENTER_STATIC_NOERR
if(spans != NULL) {
uint64_t op_gen;
op_gen = H5S__hyper_get_op_gen();
ret_value = H5S__hyper_span_nblocks_helper(spans, 0, op_gen);
}
FUNC_LEAVE_NOAPI(ret_value)
}
static hsize_t
H5S__get_select_hyper_nblocks(const H5S_t *space, hbool_t app_ref)
{
hsize_t ret_value = 0;
FUNC_ENTER_STATIC_NOERR
HDassert(space);
HDassert(space->select.sel_info.hslab->unlim_dim < 0);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
unsigned u;
for(ret_value = 1, u = 0; u < space->extent.rank; u++)
ret_value *= (app_ref ? space->select.sel_info.hslab->diminfo.app[u].count :
space->select.sel_info.hslab->diminfo.opt[u].count);
}
else
ret_value = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
FUNC_LEAVE_NOAPI(ret_value)
}
hssize_t
H5Sget_select_hyper_nblocks(hid_t spaceid)
{
H5S_t *space;
hssize_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE1("Hs", "i", spaceid);
if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
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")
if(space->select.sel_info.hslab->unlim_dim >= 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot get number of blocks for unlimited selection")
ret_value = (hssize_t)H5S__get_select_hyper_nblocks(space, TRUE);
done:
FUNC_LEAVE_API(ret_value)
}
static uint8_t
H5S__hyper_get_enc_size_real(hsize_t max_size)
{
uint8_t ret_value;
FUNC_ENTER_STATIC_NOERR
if(max_size > H5S_UINT32_MAX)
ret_value = H5S_SELECT_INFO_ENC_SIZE_8;
else
ret_value = H5S_SELECT_INFO_ENC_SIZE_4;
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_get_version_enc_size(const H5S_t *space, hsize_t block_count, uint32_t *version, uint8_t *enc_size)
{
hsize_t bounds_start[H5S_MAX_RANK];
hsize_t bounds_end[H5S_MAX_RANK];
hbool_t count_up_version = FALSE;
hbool_t bound_up_version = FALSE;
H5F_libver_t low_bound;
H5F_libver_t high_bound;
unsigned u;
uint32_t tmp_version;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDmemset(bounds_end, 0, sizeof(bounds_end));
if(space->select.sel_info.hslab->unlim_dim < 0)
if(H5S__hyper_bounds(space, bounds_start, bounds_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds")
if(block_count > H5S_UINT32_MAX)
count_up_version = TRUE;
else {
for(u = 0; u < space->extent.rank; u++)
if(bounds_end[u] > H5S_UINT32_MAX)
bound_up_version = TRUE;
}
if(H5CX_get_libver_bounds(&low_bound, &high_bound) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get low/high bounds from API context")
if(space->select.sel_info.hslab->unlim_dim >= 0)
tmp_version = H5S_HYPER_VERSION_2;
else if(H5S__hyper_is_regular(space)) {
if(count_up_version || bound_up_version)
tmp_version = H5S_HYPER_VERSION_2;
else
tmp_version = (block_count < 4) ? H5S_HYPER_VERSION_1 : H5O_sds_hyper_ver_bounds[low_bound];
} else {
if(count_up_version)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The number of blocks in hyperslab selection exceeds 2^32")
else if(bound_up_version)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The end of bounding box in hyperslab selection exceeds 2^32")
tmp_version = H5S_HYPER_VERSION_1;
}
if(tmp_version > H5O_sds_hyper_ver_bounds[high_bound])
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "Dataspace hyperslab selection version out of bounds")
*version = tmp_version;
switch(tmp_version) {
case H5S_HYPER_VERSION_1:
*enc_size = H5S_SELECT_INFO_ENC_SIZE_4;
break;
case H5S_HYPER_VERSION_2:
*enc_size = H5S_SELECT_INFO_ENC_SIZE_8;
break;
default:
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown hyperslab selection version")
break;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static hssize_t
H5S__hyper_serial_size(const H5S_t *space)
{
hsize_t block_count = 0;
uint32_t version;
uint8_t enc_size;
hssize_t ret_value = -1;
FUNC_ENTER_STATIC
HDassert(space);
if(space->select.sel_info.hslab->unlim_dim < 0)
block_count = H5S__get_select_hyper_nblocks(space, FALSE);
if(H5S__hyper_get_version_enc_size(space, block_count, &version, &enc_size) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version & enc_size")
if(version == H5S_HYPER_VERSION_2) {
HDassert(enc_size == 8);
ret_value = (hssize_t)17 + ((hssize_t)4 * (hssize_t)8 * (hssize_t)space->extent.rank);
}
else {
HDassert(version == H5S_HYPER_VERSION_1);
HDassert(enc_size == 4);
ret_value = 24;
H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, hssize_t);
ret_value += (hssize_t)(8 * space->extent.rank * block_count);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void
H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans,
hsize_t *start, hsize_t *end, hsize_t rank, uint8_t enc_size, uint8_t **p)
{
H5S_hyper_span_t *curr;
uint8_t *pp = (*p);
FUNC_ENTER_STATIC_NOERR
HDassert(spans);
HDassert(start);
HDassert(end);
HDassert(rank < H5S_MAX_RANK);
HDassert(p && pp);
curr = spans->head;
while(curr != NULL) {
if(curr->down != NULL) {
start[rank] = curr->low;
end[rank] = curr->high;
H5S__hyper_serialize_helper(curr->down, start, end, rank + 1, enc_size, &pp);
}
else {
hsize_t u;
switch(enc_size) {
case H5S_SELECT_INFO_ENC_SIZE_4:
for(u=0; u<rank; u++)
UINT32ENCODE(pp, (uint32_t)start[u]);
UINT32ENCODE(pp, (uint32_t)curr->low);
for(u=0; u<rank; u++)
UINT32ENCODE(pp, (uint32_t)end[u]);
UINT32ENCODE(pp, (uint32_t)curr->high);
break;
case H5S_SELECT_INFO_ENC_SIZE_8:
for(u=0; u<rank; u++)
UINT64ENCODE(pp, (uint64_t)start[u]);
UINT64ENCODE(pp, (uint64_t)curr->low);
for(u=0; u<rank; u++)
UINT64ENCODE(pp, (uint64_t)end[u]);
UINT64ENCODE(pp, (uint64_t)curr->high);
break;
default:
HDassert(0 && "Unknown enc size?!?");
}
}
curr = curr->next;
}
*p = pp;
FUNC_LEAVE_NOAPI_VOID
}
static herr_t
H5S__hyper_serialize(const H5S_t *space, uint8_t **p)
{
const H5S_hyper_dim_t *diminfo;
hsize_t tmp_count[H5S_MAX_RANK];
hsize_t offset[H5S_MAX_RANK];
hsize_t start[H5S_MAX_RANK];
hsize_t end[H5S_MAX_RANK];
uint8_t *pp;
uint8_t *lenp = NULL;
uint32_t len = 0;
uint32_t version;
uint8_t flags = 0;
hsize_t block_count = 0;
unsigned fast_dim;
unsigned ndims;
unsigned u;
hbool_t complete = FALSE;
hbool_t is_regular;
uint8_t enc_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space);
HDassert(p);
pp = (*p);
HDassert(pp);
ndims = space->extent.rank;
diminfo = space->select.sel_info.hslab->diminfo.opt;
if(space->select.sel_info.hslab->unlim_dim < 0)
block_count = H5S__get_select_hyper_nblocks(space, FALSE);
if(H5S__hyper_get_version_enc_size(space, block_count, &version, &enc_size) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version & enc_size")
is_regular = H5S__hyper_is_regular(space);
if(is_regular && version == H5S_HYPER_VERSION_2)
flags |= H5S_HYPER_REGULAR;
UINT32ENCODE(pp, (uint32_t)H5S_GET_SELECT_TYPE(space));
UINT32ENCODE(pp, version);
if(version == H5S_HYPER_VERSION_2)
*(pp)++ = flags;
else
UINT32ENCODE(pp, (uint32_t)0);
lenp = pp;
pp += 4;
len += 4;
UINT32ENCODE(pp, (uint32_t)ndims);
if(is_regular) {
if(version == H5S_HYPER_VERSION_2) {
HDassert(H5S_UNLIMITED == HSIZE_UNDEF);
switch(enc_size) {
case H5S_SELECT_INFO_ENC_SIZE_8:
HDassert(version == H5S_HYPER_VERSION_2);
for(u = 0; u < space->extent.rank; u++) {
UINT64ENCODE(pp, diminfo[u].start);
UINT64ENCODE(pp, diminfo[u].stride);
if(diminfo[u].count == H5S_UNLIMITED)
UINT64ENCODE(pp, H5S_UINT64_MAX)
else
UINT64ENCODE(pp, diminfo[u].count)
if(diminfo[u].block == H5S_UNLIMITED)
UINT64ENCODE(pp, H5S_UINT64_MAX)
else
UINT64ENCODE(pp, diminfo[u].block)
}
if(version == H5S_HYPER_VERSION_2)
len += (4 * space->extent.rank * 8);
break;
default:
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
break;
}
}
else {
HDassert(version == H5S_HYPER_VERSION_1);
fast_dim = ndims - 1;
H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t);
UINT32ENCODE(pp, (uint32_t)block_count);
len += 4;
for(u = 0; u < ndims; u++) {
tmp_count[u] = diminfo[u].count;
offset[u] = diminfo[u].start;
}
while(complete == FALSE) {
while(tmp_count[fast_dim] > 0) {
len += 8 * ndims;
for(u = 0; u < ndims; u++)
UINT32ENCODE(pp, (uint32_t)offset[u]);
for(u = 0; u < ndims; u++)
UINT32ENCODE(pp, (uint32_t)(offset[u] + (diminfo[u].block - 1)));
offset[fast_dim]+=diminfo[fast_dim].stride;
tmp_count[fast_dim]--;
}
if(fast_dim > 0) {
int temp_dim;
tmp_count[fast_dim] = diminfo[fast_dim].count;
temp_dim = (int)fast_dim - 1;
while(temp_dim >= 0 && complete == FALSE) {
tmp_count[temp_dim]--;
if(tmp_count[temp_dim] > 0)
break;
if(temp_dim == 0)
complete = TRUE;
tmp_count[temp_dim] = diminfo[temp_dim].count;
temp_dim--;
}
}
else
break;
for(u = 0; u < ndims; u++)
offset[u] = diminfo[u].start + diminfo[u].stride * (diminfo[u].count - tmp_count[u]);
}
}
}
else {
switch(enc_size) {
case H5S_SELECT_INFO_ENC_SIZE_4:
HDassert(version == H5S_HYPER_VERSION_1);
H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t);
UINT32ENCODE(pp, (uint32_t)block_count);
break;
default:
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
break;
}
if(version == H5S_HYPER_VERSION_1) {
len += 4;
H5_CHECK_OVERFLOW((8 * ndims * block_count), hsize_t, size_t);
len += (uint32_t)(8 * ndims * block_count);
}
H5S__hyper_serialize_helper(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, enc_size, &pp);
}
UINT32ENCODE(lenp, (uint32_t)len);
*p = pp;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_deserialize(H5S_t **space, const uint8_t **p)
{
H5S_t *tmp_space = NULL;
hsize_t dims[H5S_MAX_RANK];
hsize_t start[H5S_MAX_RANK];
hsize_t block[H5S_MAX_RANK];
uint32_t version;
uint8_t flags = 0;
uint8_t enc_size = 0;
unsigned rank;
const uint8_t *pp;
unsigned u;
herr_t ret_value=FAIL;
FUNC_ENTER_STATIC
HDassert(p);
pp = (*p);
HDassert(pp);
if(!*space) {
if(NULL == (tmp_space = H5S_create(H5S_SIMPLE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create dataspace")
}
else
tmp_space = *space;
UINT32DECODE(pp, version);
if(version < H5S_HYPER_VERSION_1 || version > H5S_HYPER_VERSION_LATEST)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "bad version number for hyperslab selection")
if(version >= (uint32_t)H5S_HYPER_VERSION_2) {
flags = *(pp)++;
pp += 4;
enc_size = H5S_SELECT_INFO_ENC_SIZE_8;
if(flags & ~H5S_SELECT_FLAG_BITS)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown flag for selection")
}
else {
pp += 8;
enc_size = H5S_SELECT_INFO_ENC_SIZE_4;
}
if(enc_size & ~H5S_SELECT_INFO_ENC_SIZE_BITS)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown size of point/offset info for selection")
UINT32DECODE(pp,rank);
if(!*space) {
HDmemset(dims, 0, (size_t)rank * sizeof(dims[0]));
if(H5S_set_extent_simple(tmp_space, rank, dims, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set dimensions")
}
else
if(rank != tmp_space->extent.rank)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of serialized selection does not match dataspace")
if(flags & H5S_HYPER_REGULAR) {
hsize_t stride[H5S_MAX_RANK];
hsize_t count[H5S_MAX_RANK];
HDassert(H5S_UNLIMITED == HSIZE_UNDEF);
HDassert(version >= H5S_HYPER_VERSION_2);
switch(enc_size) {
case H5S_SELECT_INFO_ENC_SIZE_4:
for(u = 0; u < tmp_space->extent.rank; u++) {
UINT32DECODE(pp, start[u]);
UINT32DECODE(pp, stride[u]);
UINT32DECODE(pp, count[u]);
if((uint32_t)count[u] == H5S_UINT32_MAX)
count[u] = H5S_UNLIMITED;
UINT32DECODE(pp, block[u]);
if((uint32_t)block[u] == H5S_UINT32_MAX)
block[u] = H5S_UNLIMITED;
}
break;
case H5S_SELECT_INFO_ENC_SIZE_8:
for(u = 0; u < tmp_space->extent.rank; u++) {
UINT64DECODE(pp, start[u]);
UINT64DECODE(pp, stride[u]);
UINT64DECODE(pp, count[u]);
if((uint64_t)count[u] == H5S_UINT64_MAX)
count[u] = H5S_UNLIMITED;
UINT64DECODE(pp, block[u]);
if((uint64_t)block[u] == H5S_UINT64_MAX)
block[u] = H5S_UNLIMITED;
}
break;
default:
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
break;
}
if((ret_value = H5S_select_hyperslab(tmp_space, H5S_SELECT_SET, start, stride, count, block)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't change selection")
}
else {
const hsize_t *stride;
const hsize_t *count;
hsize_t end[H5S_MAX_RANK];
hsize_t *tstart;
hsize_t *tend;
hsize_t *tblock;
size_t num_elem;
unsigned v;
switch(enc_size) {
case H5S_SELECT_INFO_ENC_SIZE_4:
UINT32DECODE(pp, num_elem);
break;
case H5S_SELECT_INFO_ENC_SIZE_8:
UINT64DECODE(pp, num_elem);
break;
default:
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
break;
}
stride = count = H5S_hyper_ones_g;
for(u = 0; u < num_elem; u++) {
switch(enc_size) {
case H5S_SELECT_INFO_ENC_SIZE_4:
for(tstart = start,v = 0; v < rank; v++, tstart++)
UINT32DECODE(pp, *tstart);
for(tend = end, v = 0; v < rank; v++, tend++)
UINT32DECODE(pp, *tend);
break;
case H5S_SELECT_INFO_ENC_SIZE_8:
for(tstart = start, v = 0; v < rank; v++, tstart++)
UINT64DECODE(pp, *tstart);
for(tend = end, v = 0; v < rank; v++, tend++)
UINT64DECODE(pp, *tend);
break;
default:
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
break;
}
for(tblock = block, tstart = start, tend = end, v = 0; v < rank; v++, tstart++, tend++, tblock++)
*tblock = (*tend - *tstart) + 1;
if((ret_value = H5S_select_hyperslab(tmp_space, (u == 0 ? H5S_SELECT_SET : H5S_SELECT_OR), start, stride, count, block)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't change selection")
}
}
*p = pp;
if(!*space)
*space = tmp_space;
done:
if(!*space && tmp_space)
if(H5S_close(tmp_space) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace")
FUNC_LEAVE_NOAPI(ret_value)
}
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)
{
const H5S_hyper_span_t *curr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(spans);
HDassert(rank < H5S_MAX_RANK);
HDassert(start);
HDassert(end);
HDassert(startblock);
HDassert(numblocks && *numblocks > 0);
HDassert(buf && *buf);
curr = spans->head;
while(curr != NULL && *numblocks > 0) {
if(curr->down != NULL) {
start[rank] = curr->low;
end[rank] = curr->high;
if(H5S__hyper_span_blocklist(curr->down, start, end, (rank + 1), startblock, numblocks, buf) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
}
else {
if(*startblock > 0) {
(*startblock)--;
}
else {
H5MM_memcpy(*buf, start, rank * sizeof(hsize_t));
(*buf) += rank;
**buf = curr->low;
(*buf)++;
H5MM_memcpy(*buf, end, rank * sizeof(hsize_t));
(*buf) += rank;
**buf = curr->high;
(*buf)++;
(*numblocks)--;
}
}
curr = curr->next;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__get_select_hyper_blocklist(H5S_t *space, hsize_t startblock,
hsize_t numblocks, hsize_t *buf)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_NOERR
HDassert(space);
HDassert(buf);
HDassert(space->select.sel_info.hslab->unlim_dim < 0);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
H5S__hyper_rebuild(space);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
const H5S_hyper_dim_t *diminfo;
hsize_t tmp_count[H5S_MAX_RANK];
hsize_t offset[H5S_MAX_RANK];
hsize_t end[H5S_MAX_RANK];
unsigned fast_dim;
unsigned ndims;
hbool_t done;
unsigned u;
ndims = space->extent.rank;
fast_dim = ndims - 1;
if(space->select.sel_info.hslab->unlim_dim >= 0)
diminfo = space->select.sel_info.hslab->diminfo.opt;
else
diminfo = space->select.sel_info.hslab->diminfo.app;
for(u = 0; u < ndims; u++) {
tmp_count[u] = diminfo[u].count;
offset[u] = diminfo[u].start;
end[u] = diminfo[u].start + (diminfo[u].block - 1);
}
done = FALSE;
while(!done && numblocks > 0) {
if(startblock > 0) {
if(startblock >= tmp_count[fast_dim]) {
startblock -= tmp_count[fast_dim];
tmp_count[fast_dim] = 0;
}
else {
offset[fast_dim] += diminfo[fast_dim].stride * startblock;
end[fast_dim] += diminfo[fast_dim].stride * startblock;
tmp_count[fast_dim] -= startblock;
startblock = 0;
}
}
while(tmp_count[fast_dim] > 0 && numblocks > 0) {
HDassert(startblock == 0);
H5MM_memcpy(buf, offset, sizeof(hsize_t) * ndims);
buf += ndims;
H5MM_memcpy(buf, end, sizeof(hsize_t) * ndims);
buf += ndims;
numblocks--;
offset[fast_dim] += diminfo[fast_dim].stride;
end[fast_dim] += diminfo[fast_dim].stride;
tmp_count[fast_dim]--;
}
if(fast_dim > 0 && numblocks > 0) {
int temp_dim;
tmp_count[fast_dim] = diminfo[fast_dim].count;
temp_dim = (int)(fast_dim - 1);
while(temp_dim >= 0 && !done) {
tmp_count[temp_dim]--;
if(tmp_count[temp_dim] > 0)
break;
tmp_count[temp_dim] = diminfo[temp_dim].count;
if(temp_dim == 0)
done = TRUE;
temp_dim--;
}
}
if(!done)
for(u = 0; u < ndims; u++) {
offset[u] = diminfo[u].start + diminfo[u].stride * (diminfo[u].count - tmp_count[u]);
end[u] = offset[u] + (diminfo[u].block - 1);
}
}
}
else {
hsize_t start[H5S_MAX_RANK];
hsize_t end[H5S_MAX_RANK];
ret_value = H5S__hyper_span_blocklist(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, &startblock, &numblocks, &buf);
}
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock,
hsize_t numblocks, hsize_t buf[])
{
H5S_t *space;
herr_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "ihh*[a2]h", spaceid, startblock, numblocks, buf);
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 dataspace")
if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_HYPERSLABS)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection")
if(space->select.sel_info.hslab->unlim_dim >= 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot get blocklist for unlimited selection")
if(numblocks > 0)
ret_value = H5S__get_select_hyper_blocklist(space, startblock, numblocks, buf);
else
ret_value = SUCCEED;
done:
FUNC_LEAVE_API(ret_value)
}
static herr_t
H5S__hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
{
const hsize_t *low_bounds, *high_bounds;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space);
HDassert(start);
HDassert(end);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
low_bounds = space->select.sel_info.hslab->diminfo.low_bounds;
high_bounds = space->select.sel_info.hslab->diminfo.high_bounds;
}
else {
low_bounds = space->select.sel_info.hslab->span_lst->low_bounds;
high_bounds = space->select.sel_info.hslab->span_lst->high_bounds;
}
if(space->select.offset_changed) {
unsigned u;
for(u = 0; u < space->extent.rank; u++) {
HDassert(low_bounds[u] <= high_bounds[u]);
if(((hssize_t)low_bounds[u] + space->select.offset[u]) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
start[u] = (hsize_t)((hssize_t)low_bounds[u] + space->select.offset[u]);
if((int)u == space->select.sel_info.hslab->unlim_dim)
end[u] = H5S_UNLIMITED;
else
end[u] = (hsize_t)((hssize_t)high_bounds[u] + space->select.offset[u]);
}
}
else {
H5MM_memcpy(start, low_bounds, sizeof(hsize_t) * space->extent.rank);
H5MM_memcpy(end, high_bounds, sizeof(hsize_t) * space->extent.rank);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_offset(const H5S_t *space, hsize_t *offset)
{
const hssize_t *sel_offset;
const hsize_t *dim_size;
hsize_t accum;
unsigned rank;
int i;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space && space->extent.rank>0);
HDassert(offset);
*offset = 0;
rank = space->extent.rank;
sel_offset = space->select.offset;
dim_size = space->extent.size;
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->diminfo.opt;
accum = 1;
for(i = (int)(rank - 1); i >= 0; i--) {
hssize_t hyp_offset = (hssize_t)diminfo[i].start + sel_offset[i];
if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i])
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
*offset += (hsize_t)(hyp_offset * (hssize_t)accum);
accum *= dim_size[i];
}
}
else {
const H5S_hyper_span_t *span;
hsize_t dim_accum[H5S_MAX_RANK];
accum = 1;
for(i = (int)(rank - 1); i >= 0; i--) {
dim_accum[i] = accum;
accum *= dim_size[i];
}
span = space->select.sel_info.hslab->span_lst->head;
i = 0;
while(span) {
hssize_t hyp_offset = (hssize_t)span->low + sel_offset[i];
if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i])
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
*offset += (hsize_t)(hyp_offset * (hssize_t)dim_accum[i]);
if(span->down) {
HDassert(span->down->head);
span = span->down->head;
}
else
span = NULL;
i++;
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5S__hyper_unlim_dim(const H5S_t *space)
{
FUNC_ENTER_STATIC_NOERR
FUNC_LEAVE_NOAPI(space->select.sel_info.hslab->unlim_dim);
}
static herr_t
H5S__hyper_num_elem_non_unlim(const H5S_t *space, hsize_t *num_elem_non_unlim)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space);
HDassert(num_elem_non_unlim);
if(space->select.sel_info.hslab->unlim_dim >= 0)
*num_elem_non_unlim = space->select.sel_info.hslab->num_elem_non_unlim;
else
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection has no unlimited dimension")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5_ATTR_PURE htri_t
H5S__hyper_is_contiguous(const H5S_t *space)
{
hbool_t small_contiguous,
large_contiguous;
unsigned u;
htri_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(space);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
const H5S_hyper_dim_t *diminfo=space->select.sel_info.hslab->diminfo.opt;
large_contiguous = TRUE;
small_contiguous = FALSE;
for(u = 0; u < space->extent.rank; u++) {
if(diminfo[u].count > 1) {
large_contiguous = FALSE;
break;
}
if(u > 0 && diminfo[u].block != space->extent.size[u]) {
large_contiguous = FALSE;
break;
}
}
if(!large_contiguous) {
small_contiguous = TRUE;
for(u = 0; u < space->extent.rank; u++) {
if(diminfo[u].count > 1) {
small_contiguous = FALSE;
break;
}
if(u < (space->extent.rank - 1) && diminfo[u].block != 1) {
small_contiguous = FALSE;
break;
}
}
}
if(large_contiguous || small_contiguous)
ret_value = TRUE;
}
else {
H5S_hyper_span_info_t *spans;
H5S_hyper_span_t *span;
large_contiguous = TRUE;
small_contiguous = FALSE;
spans = space->select.sel_info.hslab->span_lst;
span = spans->head;
if(span->next != NULL)
large_contiguous = FALSE;
else {
if(span->down != NULL) {
u = 1;
spans = span->down;
while(spans != NULL) {
span = spans->head;
if(span->next != NULL) {
large_contiguous = FALSE;
break;
}
else {
if(((span->high - span->low) + 1) != space->extent.size[u]) {
large_contiguous = FALSE;
break;
}
else {
spans = span->down;
u++;
}
}
}
}
}
if(!large_contiguous) {
small_contiguous = TRUE;
spans = space->select.sel_info.hslab->span_lst;
span = spans->head;
u = 0;
while(spans != NULL) {
span = spans->head;
if(span->next != NULL) {
small_contiguous = FALSE;
break;
}
else {
if(u < (space->extent.rank - 1) && ((span->high-span->low) + 1) != 1) {
small_contiguous = FALSE;
break;
}
else {
spans = span->down;
u++;
}
}
}
}
if(large_contiguous || small_contiguous)
ret_value = TRUE;
}
FUNC_LEAVE_NOAPI(ret_value)
}
static H5_ATTR_PURE htri_t
H5S__hyper_is_single(const H5S_t *space)
{
htri_t ret_value = TRUE;
FUNC_ENTER_STATIC_NOERR
HDassert(space);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
unsigned u;
for(u = 0; u < space->extent.rank; u++)
if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
HGOTO_DONE(FALSE)
}
else {
H5S_hyper_span_info_t *spans;
spans = space->select.sel_info.hslab->span_lst;
while(spans != NULL) {
H5S_hyper_span_t *span;
span = spans->head;
if(span->next != NULL)
HGOTO_DONE(FALSE)
else
spans = span->down;
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5S__hyper_is_regular(const H5S_t *space)
{
htri_t ret_value = FAIL;
FUNC_ENTER_STATIC_NOERR
HDassert(space);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
H5S__hyper_rebuild((H5S_t *)space);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES)
ret_value = TRUE;
else
ret_value = FALSE;
FUNC_LEAVE_NOAPI(ret_value)
}
static H5_ATTR_PURE hbool_t
H5S__hyper_spans_shape_same_helper(const H5S_hyper_span_info_t *span_info1,
const H5S_hyper_span_info_t *span_info2, hssize_t offset[],
hbool_t rest_zeros[])
{
hbool_t ret_value = TRUE;
FUNC_ENTER_PACKAGE_NOERR
HDassert(span_info1);
HDassert(span_info2);
HDassert(offset);
HDassert(rest_zeros);
if((hsize_t)((hssize_t)span_info1->low_bounds[0] + offset[0]) != span_info2->low_bounds[0])
HGOTO_DONE(FALSE)
else if((hsize_t)((hssize_t)span_info1->high_bounds[0] + offset[0]) != span_info2->high_bounds[0])
HGOTO_DONE(FALSE)
else {
const H5S_hyper_span_t *span1;
const H5S_hyper_span_t *span2;
span1 = span_info1->head;
span2 = span_info2->head;
HDassert(span1);
HDassert(span2);
while(1) {
if(span1 == NULL && span2 == NULL)
HGOTO_DONE(TRUE)
if(span1 == NULL || span2 == NULL)
HGOTO_DONE(FALSE)
if((hsize_t)((hssize_t)span1->low + offset[0]) != span2->low || (hsize_t)((hssize_t)span1->high + offset[0]) != span2->high)
HGOTO_DONE(FALSE)
if(span1->down != NULL || span2->down != NULL) {
if(rest_zeros[0]) {
if(!H5S__hyper_cmp_spans(span1->down, span2->down))
HGOTO_DONE(FALSE)
else {
}
}
else {
if(!H5S__hyper_spans_shape_same_helper(span1->down, span2->down, &offset[1], &rest_zeros[1]))
HGOTO_DONE(FALSE)
else {
}
}
}
else {
}
span1 = span1->next;
span2 = span2->next;
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5_ATTR_PURE hbool_t
H5S__hyper_spans_shape_same(const H5S_hyper_span_info_t *span_info1,
const H5S_hyper_span_info_t *span_info2, unsigned ndims)
{
const H5S_hyper_span_t *span1;
const H5S_hyper_span_t *span2;
hssize_t offset[H5S_MAX_RANK];
hbool_t rest_zeros[H5S_MAX_RANK];
hbool_t zero_offset;
unsigned u;
hbool_t ret_value = TRUE;
FUNC_ENTER_STATIC_NOERR
HDassert(span_info1);
HDassert(span_info2);
HDassert(ndims > 0);
HDmemset(offset, 0, sizeof(offset));
HDmemset(rest_zeros, 0, sizeof(rest_zeros));
span1 = span_info1->head;
span2 = span_info2->head;
zero_offset = TRUE;
for(u = 0; u < ndims; u++) {
if(span1->low != span2->low) {
offset[u] = (hssize_t)span2->low - (hssize_t)span1->low;
if(zero_offset)
zero_offset = FALSE;
}
HDassert((span1->down && span2->down) || (NULL == span1->down && NULL == span2->down));
if(span1->down) {
span1 = span1->down->head;
span2 = span2->down->head;
}
}
if(!zero_offset) {
int i;
for(i = (int)(ndims - 1); i >= 0; i--)
if(offset[i]) {
rest_zeros[i] = TRUE;
break;
}
HDassert(i >= 0);
}
if(zero_offset)
ret_value = H5S__hyper_cmp_spans(span_info1, span_info2);
else
ret_value = H5S__hyper_spans_shape_same_helper(span_info1, span_info2, offset, rest_zeros);
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5S__hyper_shape_same(const H5S_t *space1, const H5S_t *space2)
{
unsigned space1_rank;
unsigned space2_rank;
htri_t ret_value = TRUE;
FUNC_ENTER_STATIC
HDassert(space1);
HDassert(space2);
space1_rank = space1->extent.rank;
space2_rank = space2->extent.rank;
HDassert(space1_rank >= space2_rank);
HDassert(space2_rank > 0);
if(space1->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
H5S__hyper_rebuild((H5S_t *)space1);
if(space2->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
H5S__hyper_rebuild((H5S_t *)space2);
if(space1->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES
&& space2->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
int space1_dim;
int space2_dim;
space1_dim = (int)space1_rank - 1;
space2_dim = (int)space2_rank - 1;
while(space2_dim >= 0) {
if(space1->select.sel_info.hslab->diminfo.opt[space1_dim].stride !=
space2->select.sel_info.hslab->diminfo.opt[space2_dim].stride)
HGOTO_DONE(FALSE)
if(space1->select.sel_info.hslab->diminfo.opt[space1_dim].count !=
space2->select.sel_info.hslab->diminfo.opt[space2_dim].count)
HGOTO_DONE(FALSE)
if(space1->select.sel_info.hslab->diminfo.opt[space1_dim].block !=
space2->select.sel_info.hslab->diminfo.opt[space2_dim].block)
HGOTO_DONE(FALSE)
space1_dim--;
space2_dim--;
}
while(space1_dim >= 0) {
if(space1->select.sel_info.hslab->diminfo.opt[space1_dim].block != 1)
HGOTO_DONE(FALSE)
space1_dim--;
}
}
else {
H5S_hyper_span_info_t *spans1;
if(NULL == space1->select.sel_info.hslab->span_lst)
if(H5S__hyper_generate_spans((H5S_t *)space1) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for hyperslab selection")
if(NULL == space2->select.sel_info.hslab->span_lst)
if(H5S__hyper_generate_spans((H5S_t *)space2) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for hyperslab selection")
if(space1_rank > space2_rank) {
unsigned diff_rank = space1_rank - space2_rank;
spans1 = space1->select.sel_info.hslab->span_lst;
while(diff_rank > 0) {
H5S_hyper_span_t *span;
span = spans1->head;
if(span->next)
HGOTO_DONE(FALSE)
if(span->low != span->high)
HGOTO_DONE(FALSE)
spans1 = span->down;
diff_rank--;
}
HDassert(spans1);
}
else
spans1 = space1->select.sel_info.hslab->span_lst;
ret_value = H5S__hyper_spans_shape_same(spans1, space2->select.sel_info.hslab->span_lst, space2_rank);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_release(H5S_t *space)
{
FUNC_ENTER_STATIC_NOERR
HDassert(space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space));
space->select.num_elem = 0;
if(space->select.sel_info.hslab) {
if(space->select.sel_info.hslab->span_lst != NULL)
H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst);
space->select.sel_info.hslab = H5FL_FREE(H5S_hyper_sel_t, space->select.sel_info.hslab);
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static H5S_hyper_span_t *
H5S__hyper_coord_to_span(unsigned rank, const hsize_t *coords)
{
H5S_hyper_span_t *new_span;
H5S_hyper_span_info_t *down = NULL;
H5S_hyper_span_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(rank > 0);
HDassert(coords);
if(rank > 1) {
if(NULL == (down = H5S__hyper_new_span_info(rank - 1)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
H5MM_memcpy(down->low_bounds, &coords[1], (rank - 1) * sizeof(hsize_t));
H5MM_memcpy(down->high_bounds, &coords[1], (rank - 1) * sizeof(hsize_t));
if(NULL == (down->head = H5S__hyper_coord_to_span(rank - 1, &coords[1])))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
down->tail = down->head;
}
if(NULL == (new_span = H5S__hyper_new_span(coords[0], coords[0], down, NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
ret_value = new_span;
done:
if(ret_value == NULL && down != NULL)
H5S__hyper_free_span_info(down);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree,
unsigned rank, const hsize_t *coords, int *first_dim_modified)
{
H5S_hyper_span_t *tail_span;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(span_tree);
HDassert(rank > 0);
HDassert(coords);
HDassert(first_dim_modified);
tail_span = span_tree->tail;
if(coords[0] >= tail_span->low && coords[0] <= tail_span->high) {
H5S_hyper_span_t *prev_down_tail_span;
hsize_t prev_down_tail_span_high;
prev_down_tail_span = tail_span->down->tail;
prev_down_tail_span_high = tail_span->down->tail->high;
HDassert(rank > 1);
if(H5S__hyper_add_span_element_helper(tail_span->down, rank - 1, &coords[1], first_dim_modified) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert coordinate into span tree")
if(*first_dim_modified >= 0) {
unsigned first_dim;
hbool_t first_dim_set = FALSE;
unsigned u;
first_dim = (unsigned)(*first_dim_modified + 1);
*first_dim_modified = -1;
for(u = first_dim; u < rank; u++) {
if(coords[u] > span_tree->high_bounds[u]) {
span_tree->high_bounds[u] = coords[u];
if(!first_dim_set) {
*first_dim_modified = (int)u;
first_dim_set = TRUE;
}
}
}
}
if(tail_span->down->tail != prev_down_tail_span ||
prev_down_tail_span_high != tail_span->down->tail->high) {
H5S_hyper_span_t *stop_span;
H5S_hyper_span_t *tmp_span;
uint64_t op_gen;
if(tail_span->down->tail != prev_down_tail_span) {
HDassert(prev_down_tail_span->next == tail_span->down->tail);
stop_span = prev_down_tail_span;
}
else {
HDassert(prev_down_tail_span_high != tail_span->down->tail->high);
stop_span = tail_span->down->tail;
}
op_gen = H5S__hyper_get_op_gen();
tmp_span = tail_span->down->head;
while(tmp_span != stop_span) {
hbool_t attempt_merge_spans = FALSE;
if(NULL == tmp_span->down) {
if(tmp_span->next == stop_span)
attempt_merge_spans = TRUE;
}
else {
if(tmp_span->down->op_info[0].op_gen != op_gen) {
if(H5S__hyper_cmp_spans(tmp_span->down, stop_span->down))
attempt_merge_spans = TRUE;
tmp_span->down->op_info[0].op_gen = op_gen;
}
}
if(attempt_merge_spans) {
if(tmp_span->high + 1 == stop_span->low) {
tmp_span->high++;
if(stop_span == prev_down_tail_span) {
HDassert(stop_span->next == tail_span->down->tail);
tmp_span->next = stop_span->next;
}
else {
HDassert(tmp_span->next == tail_span->down->tail);
tmp_span->next = NULL;
tail_span->down->tail = tmp_span;
}
H5S__hyper_free_span(stop_span);
}
else if(stop_span->down) {
H5S__hyper_free_span_info(stop_span->down);
stop_span->down = tmp_span->down;
stop_span->down->count++;
}
break;
}
tmp_span = tmp_span->next;
}
}
}
else {
unsigned u;
if(rank == 1 && (tail_span->high + 1) == coords[0])
tail_span->high++;
else {
H5S_hyper_span_t *new_span;
if(NULL == (new_span = H5S__hyper_coord_to_span(rank, coords)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab spans for coordinate")
tail_span->next = new_span;
span_tree->tail = new_span;
}
HDassert(coords[0] > span_tree->high_bounds[0]);
span_tree->high_bounds[0] = coords[0];
for(u = 1; u < rank; u++)
if(coords[u] > span_tree->high_bounds[u])
span_tree->high_bounds[u] = coords[u];
*first_dim_modified = 0;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5S_hyper_add_span_element(H5S_t *space, unsigned rank, const hsize_t *coords)
{
H5S_hyper_span_info_t *head = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space);
HDassert(rank > 0);
HDassert(coords);
HDassert(space->extent.rank == rank);
if(NULL == space->select.sel_info.hslab) {
if(NULL == (head = H5S__hyper_new_span_info(rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span info")
H5MM_memcpy(head->low_bounds, coords, rank * sizeof(hsize_t));
H5MM_memcpy(head->high_bounds, coords, rank * sizeof(hsize_t));
head->count = 1;
if(NULL == (head->head = H5S__hyper_coord_to_span(rank, coords)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab spans for coordinate")
head->tail = head->head;
if(NULL == (space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab selection")
space->select.sel_info.hslab->span_lst = head;
space->select.type = H5S_sel_hyper;
space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
space->select.sel_info.hslab->unlim_dim = -1;
space->select.num_elem = 1;
}
else {
int first_dim_modified = -1;
if(H5S__hyper_add_span_element_helper(space->select.sel_info.hslab->span_lst, rank, coords, &first_dim_modified) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert coordinate into span tree")
space->select.num_elem++;
}
done:
if(ret_value < 0)
if(head)
H5S__hyper_free_span_info(head);
FUNC_LEAVE_NOAPI(ret_value)
}
static hbool_t
H5S__hyper_intersect_block_helper(H5S_hyper_span_info_t *spans,
unsigned rank, const hsize_t *start, const hsize_t *end, unsigned op_info_i,
uint64_t op_gen)
{
hbool_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(spans);
HDassert(start);
HDassert(end);
if(spans->op_info[op_info_i].op_gen != op_gen) {
H5S_hyper_span_t *curr;
unsigned u;
for(u = 0; u < rank; u++)
if(start[u] > spans->high_bounds[u] || end[u] < spans->low_bounds[u])
HGOTO_DONE(FALSE)
curr = spans->head;
while(curr != NULL) {
if(curr->high < *start)
curr = curr->next;
else if(curr->low > *end)
HGOTO_DONE(FALSE)
else {
if(curr->down == NULL)
HGOTO_DONE(TRUE)
else {
if(H5S__hyper_intersect_block_helper(curr->down, rank - 1, start + 1, end + 1, op_info_i, op_gen))
HGOTO_DONE(TRUE)
curr = curr->next;
}
}
}
spans->op_info[op_info_i].op_gen = op_gen;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5S__hyper_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end)
{
htri_t ret_value = FAIL;
FUNC_ENTER_STATIC_NOERR
HDassert(space);
HDassert(H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space));
HDassert(start);
HDassert(end);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
H5S__hyper_rebuild((H5S_t *)space);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
hbool_t single_block;
unsigned u;
single_block = TRUE;
for(u = 0; u < space->extent.rank; u++)
if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
single_block = FALSE;
if(single_block)
HGOTO_DONE(TRUE)
else {
for(u = 0; u < space->extent.rank; u++) {
if(start[u] > space->select.sel_info.hslab->diminfo.opt[u].start) {
hsize_t adj_start;
hsize_t nstride;
adj_start = start[u] - space->select.sel_info.hslab->diminfo.opt[u].start;
if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
nstride = adj_start / space->select.sel_info.hslab->diminfo.opt[u].stride;
else
nstride = 0;
HDassert(nstride <= space->select.sel_info.hslab->diminfo.opt[u].count);
adj_start -= nstride * space->select.sel_info.hslab->diminfo.opt[u].stride;
if(adj_start >= space->select.sel_info.hslab->diminfo.opt[u].block) {
hsize_t adj_end;
adj_end = end[u] - space->select.sel_info.hslab->diminfo.opt[u].start;
adj_end -= nstride * space->select.sel_info.hslab->diminfo.opt[u].stride;
if(adj_end < space->select.sel_info.hslab->diminfo.opt[u].stride)
HGOTO_DONE(FALSE)
}
}
}
HGOTO_DONE(TRUE)
}
}
else {
uint64_t op_gen;
op_gen = H5S__hyper_get_op_gen();
ret_value = H5S__hyper_intersect_block_helper(space->select.sel_info.hslab->span_lst, space->extent.rank, start, end, 0, op_gen);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void
H5S__hyper_adjust_u_helper(H5S_hyper_span_info_t *spans, unsigned rank,
const hsize_t *offset, unsigned op_info_i, uint64_t op_gen)
{
FUNC_ENTER_STATIC_NOERR
HDassert(spans);
HDassert(offset);
if(spans->op_info[op_info_i].op_gen != op_gen) {
H5S_hyper_span_t *span;
unsigned u;
for(u = 0; u < rank; u++) {
HDassert(spans->low_bounds[u] >= offset[u]);
spans->low_bounds[u] -= offset[u];
spans->high_bounds[u] -= offset[u];
}
span = spans->head;
while(span != NULL) {
HDassert(span->low >= *offset);
span->low -= *offset;
span->high -= *offset;
if(span->down != NULL)
H5S__hyper_adjust_u_helper(span->down, rank - 1, offset + 1, op_info_i, op_gen);
span = span->next;
}
spans->op_info[op_info_i].op_gen = op_gen;
}
FUNC_LEAVE_NOAPI_VOID
}
static herr_t
H5S__hyper_adjust_u(H5S_t *space, const hsize_t *offset)
{
hbool_t non_zero_offset = FALSE;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(space);
HDassert(offset);
for(u = 0; u < space->extent.rank; u++)
if(0 != offset[u]) {
non_zero_offset = TRUE;
break;
}
if(non_zero_offset) {
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->diminfo.opt[u].start >= offset[u]);
space->select.sel_info.hslab->diminfo.opt[u].start -= offset[u];
HDassert(space->select.sel_info.hslab->diminfo.low_bounds[u] >= offset[u]);
space->select.sel_info.hslab->diminfo.low_bounds[u] -= offset[u];
space->select.sel_info.hslab->diminfo.high_bounds[u] -= offset[u];
}
}
if(space->select.sel_info.hslab->span_lst) {
uint64_t op_gen;
op_gen = H5S__hyper_get_op_gen();
H5S__hyper_adjust_u_helper(space->select.sel_info.hslab->span_lst, space->extent.rank, offset, 0, op_gen);
}
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_project_scalar(const H5S_t *space, hsize_t *offset)
{
hsize_t block[H5S_MAX_RANK];
FUNC_ENTER_STATIC_NOERR
HDassert(space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space));
HDassert(offset);
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->diminfo.opt;
unsigned u;
for(u = 0; u < space->extent.rank; u++) {
HDassert(1 == diminfo[u].count);
HDassert(1 == diminfo[u].block);
HDassert(diminfo[u].start == space->select.sel_info.hslab->diminfo.low_bounds[u]);
block[u] = diminfo[u].start;
}
}
else {
const H5S_hyper_span_t *curr;
unsigned curr_dim;
curr = space->select.sel_info.hslab->span_lst->head;
curr_dim = 0;
while(1) {
HDassert(NULL == curr->next);
HDassert(curr->low == curr->high);
HDassert(curr_dim < space->extent.rank);
block[curr_dim] = curr->low;
if(curr->down) {
curr = curr->down->head;
curr_dim++;
}
else
break;
}
}
*offset = H5VM_array_offset(space->extent.rank, space->extent.size, block);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_project_simple_lower(const H5S_t *base_space, H5S_t *new_space)
{
H5S_hyper_span_info_t *down;
unsigned curr_dim;
FUNC_ENTER_STATIC_NOERR
HDassert(base_space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(base_space));
HDassert(new_space);
HDassert(new_space->extent.rank < base_space->extent.rank);
down = base_space->select.sel_info.hslab->span_lst;
curr_dim = 0;
while(down && curr_dim < (base_space->extent.rank - new_space->extent.rank)) {
HDassert(NULL == down->head->next);
down = down->head->down;
curr_dim++;
}
HDassert(down);
new_space->select.sel_info.hslab->span_lst = down;
new_space->select.sel_info.hslab->span_lst->count++;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5S__hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space)
{
H5S_hyper_span_t *prev_span = NULL;
unsigned delta_rank;
unsigned curr_dim;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(base_space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(base_space));
HDassert(new_space);
HDassert(new_space->extent.rank > base_space->extent.rank);
new_space->select.sel_info.hslab->span_lst = NULL;
curr_dim = 0;
delta_rank = (new_space->extent.rank - base_space->extent.rank);
while(curr_dim < delta_rank) {
H5S_hyper_span_info_t *new_span_info;
H5S_hyper_span_t *new_span;
if(NULL == (new_span_info = H5S__hyper_new_span_info(new_space->extent.rank))) {
if(prev_span)
H5S__hyper_free_span(prev_span);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span info")
}
if(prev_span)
prev_span->down = new_span_info;
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_ARR_FREE(hbounds_t, new_span_info);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
}
new_span_info->count = 1;
new_span_info->head = new_span;
new_span_info->tail = new_span;
for(u = 0; u < delta_rank; u++) {
new_span_info->low_bounds[u] = 0;
new_span_info->high_bounds[u] = 0;
}
for(; u < new_space->extent.rank; u++) {
new_span_info->low_bounds[u] = base_space->select.sel_info.hslab->span_lst->low_bounds[u - delta_rank];
new_span_info->high_bounds[u] = base_space->select.sel_info.hslab->span_lst->high_bounds[u - delta_rank];
}
if(NULL == new_space->select.sel_info.hslab->span_lst)
new_space->select.sel_info.hslab->span_lst = new_span_info;
prev_span = new_span;
curr_dim++;
}
HDassert(new_space->select.sel_info.hslab->span_lst);
HDassert(prev_span);
prev_span->down = base_space->select.sel_info.hslab->span_lst;
prev_span->down->count++;
done:
if(ret_value < 0 && new_space->select.sel_info.hslab->span_lst) {
if(new_space->select.sel_info.hslab->span_lst->head)
H5S__hyper_free_span(new_space->select.sel_info.hslab->span_lst->head);
new_space->select.sel_info.hslab->span_lst = (H5S_hyper_span_info_t *)H5FL_ARR_FREE(hbounds_t, new_space->select.sel_info.hslab->span_lst);
}
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_project_simple(const H5S_t *base_space, H5S_t *new_space,
hsize_t *offset)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(base_space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(base_space));
HDassert(new_space);
HDassert(offset);
if(H5S_SELECT_RELEASE(new_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
if(NULL == (new_space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info")
new_space->select.sel_info.hslab->unlim_dim = -1;
if(base_space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
unsigned base_space_dim;
unsigned new_space_dim;
unsigned u;
if(new_space->extent.rank < base_space->extent.rank) {
const H5S_hyper_dim_t *opt_diminfo = base_space->select.sel_info.hslab->diminfo.opt;
hsize_t block[H5S_MAX_RANK];
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);
base_space_dim = base_space->extent.rank - new_space->extent.rank;
new_space_dim = 0;
}
else {
HDassert(new_space->extent.rank > base_space->extent.rank);
*offset = 0;
for(new_space_dim = 0; new_space_dim < (new_space->extent.rank - base_space->extent.rank); new_space_dim++) {
new_space->select.sel_info.hslab->diminfo.app[new_space_dim].start = 0;
new_space->select.sel_info.hslab->diminfo.app[new_space_dim].stride = 1;
new_space->select.sel_info.hslab->diminfo.app[new_space_dim].count = 1;
new_space->select.sel_info.hslab->diminfo.app[new_space_dim].block = 1;
new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].start = 0;
new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].stride = 1;
new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].count = 1;
new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].block = 1;
}
base_space_dim = 0;
}
while(base_space_dim < base_space->extent.rank) {
new_space->select.sel_info.hslab->diminfo.app[new_space_dim].start =
base_space->select.sel_info.hslab->diminfo.app[base_space_dim].start;
new_space->select.sel_info.hslab->diminfo.app[new_space_dim].stride =
base_space->select.sel_info.hslab->diminfo.app[base_space_dim].stride;
new_space->select.sel_info.hslab->diminfo.app[new_space_dim].count =
base_space->select.sel_info.hslab->diminfo.app[base_space_dim].count;
new_space->select.sel_info.hslab->diminfo.app[new_space_dim].block =
base_space->select.sel_info.hslab->diminfo.app[base_space_dim].block;
new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].start =
base_space->select.sel_info.hslab->diminfo.opt[base_space_dim].start;
new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].stride =
base_space->select.sel_info.hslab->diminfo.opt[base_space_dim].stride;
new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].count =
base_space->select.sel_info.hslab->diminfo.opt[base_space_dim].count;
new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].block =
base_space->select.sel_info.hslab->diminfo.opt[base_space_dim].block;
base_space_dim++;
new_space_dim++;
}
for(u = 0; u < new_space->extent.rank; u++) {
new_space->select.sel_info.hslab->diminfo.low_bounds[u] = new_space->select.sel_info.hslab->diminfo.opt[u].start;
new_space->select.sel_info.hslab->diminfo.high_bounds[u] = new_space->select.sel_info.hslab->diminfo.low_bounds[u] + new_space->select.sel_info.hslab->diminfo.opt[u].stride * (new_space->select.sel_info.hslab->diminfo.opt[u].count - 1) + (new_space->select.sel_info.hslab->diminfo.opt[u].block - 1);
}
new_space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
new_space->select.sel_info.hslab->span_lst = NULL;
}
else {
if(new_space->extent.rank < base_space->extent.rank) {
const H5S_hyper_span_t *curr;
hsize_t block[H5S_MAX_RANK];
unsigned curr_dim;
HDmemset(block, 0, sizeof(block));
curr = base_space->select.sel_info.hslab->span_lst->head;
curr_dim = 0;
while(curr && curr_dim < (base_space->extent.rank - new_space->extent.rank)) {
block[curr_dim] = curr->low;
curr = curr->down->head;
curr_dim++;
}
*offset = H5VM_array_offset(base_space->extent.rank, base_space->extent.size, block);
if(H5S__hyper_project_simple_lower(base_space, new_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't project hyperslab selection into less dimensions")
}
else {
HDassert(new_space->extent.rank > base_space->extent.rank);
*offset = 0;
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")
}
new_space->select.sel_info.hslab->diminfo_valid = base_space->select.sel_info.hslab->diminfo_valid;
}
new_space->select.num_elem = base_space->select.num_elem;
new_space->select.type = H5S_sel_hyper;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void
H5S__hyper_adjust_s_helper(H5S_hyper_span_info_t *spans, unsigned rank,
const hssize_t *offset, unsigned op_info_i, uint64_t op_gen)
{
FUNC_ENTER_STATIC_NOERR
HDassert(spans);
HDassert(offset);
if(spans->op_info[op_info_i].op_gen != op_gen) {
H5S_hyper_span_t *span;
unsigned u;
for(u = 0; u < rank; u++) {
HDassert((hssize_t)spans->low_bounds[u] >= offset[u]);
spans->low_bounds[u] = (hsize_t)((hssize_t)spans->low_bounds[u] - offset[u]);
spans->high_bounds[u] = (hsize_t)((hssize_t)spans->high_bounds[u] - offset[u]);
}
span = spans->head;
while(span != NULL) {
HDassert((hssize_t)span->low >= *offset);
span->low = (hsize_t)((hssize_t)span->low - *offset);
span->high = (hsize_t)((hssize_t)span->high - *offset);
if(span->down != NULL)
H5S__hyper_adjust_s_helper(span->down, rank - 1, offset + 1, op_info_i, op_gen);
span = span->next;
}
spans->op_info[op_info_i].op_gen = op_gen;
}
FUNC_LEAVE_NOAPI_VOID
}
static herr_t
H5S__hyper_adjust_s(H5S_t *space, const hssize_t *offset)
{
hbool_t non_zero_offset = FALSE;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space);
HDassert(offset);
for(u = 0; u < space->extent.rank; u++)
if(0 != offset[u]) {
non_zero_offset = TRUE;
break;
}
if(non_zero_offset) {
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->diminfo.opt[u].start >= offset[u]);
space->select.sel_info.hslab->diminfo.opt[u].start = (hsize_t)((hssize_t)space->select.sel_info.hslab->diminfo.opt[u].start - offset[u]);
HDassert((hssize_t)space->select.sel_info.hslab->diminfo.low_bounds[u] >= offset[u]);
space->select.sel_info.hslab->diminfo.low_bounds[u] = (hsize_t)((hssize_t)space->select.sel_info.hslab->diminfo.low_bounds[u] - offset[u]);
space->select.sel_info.hslab->diminfo.high_bounds[u] = (hsize_t)((hssize_t)space->select.sel_info.hslab->diminfo.high_bounds[u] - offset[u]);
}
}
if(space->select.sel_info.hslab->span_lst) {
uint64_t op_gen;
op_gen = H5S__hyper_get_op_gen();
H5S__hyper_adjust_s_helper(space->select.sel_info.hslab->span_lst, space->extent.rank, offset, 0, op_gen);
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset)
{
htri_t ret_value = FALSE;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space);
HDassert(old_offset);
if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS && space->select.offset_changed) {
unsigned u;
for(u = 0; u < space->extent.rank; u++) {
old_offset[u] = space->select.offset[u];
space->select.offset[u] = -space->select.offset[u];
}
if(H5S__hyper_adjust_s(space, space->select.offset) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust selection")
HDmemset(space->select.offset, 0, sizeof(hssize_t) * space->extent.rank);
ret_value = TRUE;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space);
HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
if(H5S__hyper_adjust_s(space, old_offset) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust selection")
H5MM_memcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_append_span(H5S_hyper_span_info_t **span_tree, unsigned ndims,
hsize_t low, hsize_t high, H5S_hyper_span_info_t *down)
{
H5S_hyper_span_t *new_span = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(span_tree);
if(*span_tree == NULL) {
if(NULL == (new_span = H5S__hyper_new_span(low, high, down, NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
if(NULL == (*span_tree = H5S__hyper_new_span_info(ndims)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
(*span_tree)->count = 1;
(*span_tree)->head = new_span;
(*span_tree)->tail = new_span;
(*span_tree)->low_bounds[0] = low;
(*span_tree)->high_bounds[0] = high;
if(down) {
HDassert(ndims > 1);
H5MM_memcpy(&((*span_tree)->low_bounds[1]), down->low_bounds, sizeof(hsize_t) * (ndims - 1));
H5MM_memcpy(&((*span_tree)->high_bounds[1]), down->high_bounds, sizeof(hsize_t) * (ndims - 1));
}
}
else {
htri_t down_cmp = (-1);
if((((*span_tree)->tail->high + 1) == low) &&
(down_cmp = H5S__hyper_cmp_spans(down, (*span_tree)->tail->down))) {
(*span_tree)->tail->high = high;
(*span_tree)->high_bounds[0] = high;
}
else {
H5S_hyper_span_info_t *new_down;
HDassert(down_cmp != TRUE);
if(down) {
if(down_cmp < 0 && (down_cmp = H5S__hyper_cmp_spans(down, (*span_tree)->tail->down)))
new_down = (*span_tree)->tail->down;
else
new_down = down;
}
else
new_down = NULL;
if(NULL == (new_span = H5S__hyper_new_span(low, high, new_down, NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
(*span_tree)->high_bounds[0] = high;
if(down) {
HDassert(ndims > 1);
HDassert(down_cmp >= 0);
if(down_cmp == FALSE) {
unsigned u;
for(u = 0; u < (ndims - 1); u++) {
if(down->low_bounds[u] < (*span_tree)->low_bounds[u + 1])
(*span_tree)->low_bounds[u + 1] = down->low_bounds[u];
if(down->high_bounds[u] > (*span_tree)->high_bounds[u + 1])
(*span_tree)->high_bounds[u + 1] = down->high_bounds[u];
}
}
}
(*span_tree)->tail->next = new_span;
(*span_tree)->tail = new_span;
}
}
done:
if(ret_value < 0)
if(new_span)
H5S__hyper_free_span(new_span);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_spans,
unsigned selector, unsigned ndims,
H5S_hyper_span_info_t **a_not_b, H5S_hyper_span_info_t **a_and_b,
H5S_hyper_span_info_t **b_not_a)
{
hbool_t need_a_not_b;
hbool_t need_a_and_b;
hbool_t need_b_not_a;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(a_spans);
HDassert(b_spans);
HDassert(a_not_b);
HDassert(a_and_b);
HDassert(b_not_a);
need_a_not_b = ((selector & H5S_HYPER_COMPUTE_A_NOT_B) != 0);
need_a_and_b = ((selector & H5S_HYPER_COMPUTE_A_AND_B) != 0);
need_b_not_a = ((selector & H5S_HYPER_COMPUTE_B_NOT_A) != 0);
if(a_spans == NULL && b_spans == NULL) {
*a_not_b = NULL;
*a_and_b = NULL;
*b_not_a = NULL;
}
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, ndims)))
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree")
}
else
*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, ndims)))
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree")
}
else
*a_not_b = NULL;
}
else {
if(H5S__hyper_cmp_spans(a_spans, b_spans)) {
*a_not_b = NULL;
*b_not_a = NULL;
if(need_a_and_b) {
if(NULL == (*a_and_b = H5S__hyper_copy_span(a_spans, ndims)))
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree")
}
else
*a_and_b = NULL;
}
else {
H5S_hyper_span_t *span_a;
H5S_hyper_span_t *span_b;
hbool_t recover_a, recover_b;
span_a = a_spans->head;
span_b = b_spans->head;
recover_a = recover_b = FALSE;
while(span_a != NULL && span_b != NULL) {
H5S_hyper_span_info_t *down_a_not_b;
H5S_hyper_span_info_t *down_a_and_b;
H5S_hyper_span_info_t *down_b_not_a;
H5S_hyper_span_t *tmp_span;
if(span_a->high < span_b->low) {
if(need_a_not_b)
if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_a->high, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
}
else if(span_a->low < span_b->low && (span_a->high >= span_b->low && span_a->high <= span_b->high)) {
if(need_a_not_b)
if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_b->low - 1, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
HDassert((span_a->down != NULL && span_b->down != NULL) || (span_a->down == NULL && span_b->down == NULL));
if(span_a->down == NULL) {
if(need_a_and_b)
if(H5S__hyper_append_span(a_and_b, ndims, span_b->low, span_a->high, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
down_a_not_b = NULL;
down_a_and_b = NULL;
down_b_not_a = NULL;
if(H5S__hyper_clip_spans(span_a->down, span_b->down, selector, ndims - 1, &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")
if(down_a_not_b) {
HDassert(need_a_not_b == TRUE);
if(H5S__hyper_append_span(a_not_b, ndims, span_b->low, span_a->high, down_a_not_b) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_a_not_b);
}
if(down_a_and_b) {
HDassert(need_a_and_b == TRUE);
if(H5S__hyper_append_span(a_and_b, ndims, span_b->low, span_a->high, down_a_and_b) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_a_and_b);
}
if(down_b_not_a) {
HDassert(need_b_not_a == TRUE);
if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_a->high, down_b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_b_not_a);
}
}
if(span_a->high < span_b->high) {
if(NULL == (tmp_span = H5S__hyper_new_span(span_a->high + 1, span_b->high, span_b->down, span_b->next)))
HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, tmp_span);
recover_b = TRUE;
}
else {
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
}
else if(span_a->low < span_b->low && span_a->high > span_b->high) {
if(need_a_not_b)
if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_b->low - 1, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
HDassert((span_a->down != NULL && span_b->down != NULL) || (span_a->down == NULL && span_b->down == NULL));
if(span_a->down == NULL) {
if(need_a_and_b)
if(H5S__hyper_append_span(a_and_b, ndims, span_b->low, span_b->high, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
down_a_not_b = NULL;
down_a_and_b = NULL;
down_b_not_a = NULL;
if(H5S__hyper_clip_spans(span_a->down, span_b->down, selector, ndims - 1, &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")
if(down_a_not_b) {
HDassert(need_a_not_b == TRUE);
if(H5S__hyper_append_span(a_not_b, ndims, span_b->low, span_b->high, down_a_not_b) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_a_not_b);
}
if(down_a_and_b) {
HDassert(need_a_and_b == TRUE);
if(H5S__hyper_append_span(a_and_b, ndims, span_b->low, span_b->high, down_a_and_b) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_a_and_b);
}
if(down_b_not_a) {
HDassert(need_b_not_a == TRUE);
if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_b->high, down_b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_b_not_a);
}
}
if(NULL == (tmp_span = H5S__hyper_new_span(span_b->high + 1, span_a->high, span_a->down, span_a->next)))
HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, tmp_span);
recover_a = TRUE;
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
else if(span_a->low >= span_b->low && span_a->high <= span_b->high) {
if(span_a->low > span_b->low) {
if(need_b_not_a)
if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_a->low - 1, span_b->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
}
HDassert((span_a->down != NULL && span_b->down != NULL) || (span_a->down == NULL && span_b->down == NULL));
if(span_a->down == NULL) {
if(need_a_and_b)
if(H5S__hyper_append_span(a_and_b, ndims, span_a->low, span_a->high, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
down_a_not_b = NULL;
down_a_and_b = NULL;
down_b_not_a = NULL;
if(H5S__hyper_clip_spans(span_a->down, span_b->down, selector, ndims - 1, &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")
if(down_a_not_b) {
HDassert(need_a_not_b == TRUE);
if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_a->high, down_a_not_b) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_a_not_b);
}
if(down_a_and_b) {
HDassert(need_a_and_b == TRUE);
if(H5S__hyper_append_span(a_and_b, ndims, span_a->low, span_a->high, down_a_and_b) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_a_and_b);
}
if(down_b_not_a) {
HDassert(need_b_not_a == TRUE);
if(H5S__hyper_append_span(b_not_a, ndims, span_a->low, span_a->high, down_b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_b_not_a);
}
}
if(span_a->high < span_b->high) {
if(NULL == (tmp_span = H5S__hyper_new_span(span_a->high + 1, span_b->high, span_b->down, span_b->next)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, tmp_span);
recover_b = TRUE;
}
else {
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
}
else if((span_a->low >= span_b->low && span_a->low <= span_b->high) && span_a->high > span_b->high) {
if(span_a->low > span_b->low) {
if(need_b_not_a)
if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_a->low - 1, span_b->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
}
HDassert((span_a->down != NULL && span_b->down != NULL) || (span_a->down == NULL && span_b->down == NULL));
if(span_a->down == NULL) {
if(need_a_and_b)
if(H5S__hyper_append_span(a_and_b, ndims, span_a->low, span_b->high, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
down_a_not_b = NULL;
down_a_and_b = NULL;
down_b_not_a = NULL;
if(H5S__hyper_clip_spans(span_a->down, span_b->down, selector, ndims - 1, &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")
if(down_a_not_b) {
HDassert(need_a_not_b == TRUE);
if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_b->high, down_a_not_b) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_a_not_b);
}
if(down_a_and_b) {
HDassert(need_a_and_b == TRUE);
if(H5S__hyper_append_span(a_and_b, ndims, span_a->low, span_b->high, down_a_and_b) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_a_and_b);
}
if(down_b_not_a) {
HDassert(need_b_not_a == TRUE);
if(H5S__hyper_append_span(b_not_a, ndims, span_a->low, span_b->high, down_b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(down_b_not_a);
}
}
if(NULL == (tmp_span = H5S__hyper_new_span(span_b->high + 1, span_a->high, span_a->down, span_a->next)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, tmp_span);
recover_a = TRUE;
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
else {
if(need_b_not_a)
if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_b->high, span_b->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
}
if(span_a != NULL && span_b == NULL) {
if(need_a_not_b) {
while(span_a != NULL) {
if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_a->high, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
}
}
else {
if(recover_a)
H5S__hyper_free_span(span_a);
}
}
else if(span_a == NULL && span_b != NULL) {
if(need_b_not_a) {
while(span_b != NULL) {
if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_b->high, span_b->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
}
else {
if(recover_b)
H5S__hyper_free_span(span_b);
}
}
else
HDassert(span_a == NULL && span_b == NULL);
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
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,
unsigned ndims)
{
H5S_hyper_span_info_t *merged_spans = NULL;
H5S_hyper_span_info_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert((a_spans != NULL && b_spans != NULL) || (a_spans == NULL && b_spans == NULL));
if(H5S__hyper_cmp_spans(a_spans, b_spans)) {
if(a_spans == NULL)
merged_spans = NULL;
else {
if(NULL == (merged_spans = H5S__hyper_copy_span(a_spans, ndims)))
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "can't copy hyperslab span tree")
}
}
else {
H5S_hyper_span_t *span_a;
H5S_hyper_span_t *span_b;
hbool_t recover_a, recover_b;
span_a = a_spans->head;
span_b = b_spans->head;
recover_a = recover_b = FALSE;
while(span_a != NULL && span_b != NULL) {
H5S_hyper_span_info_t *tmp_spans;
H5S_hyper_span_t *tmp_span;
if(span_a->high < span_b->low) {
if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_a->high, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
}
else if(span_a->low < span_b->low && (span_a->high >= span_b->low && span_a->high <= span_b->high)) {
if(H5S__hyper_cmp_spans(span_a->down, span_b->down)) {
if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_a->high, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
}
else {
if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_b->low - 1, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
tmp_spans = H5S__hyper_merge_spans_helper(span_a->down, span_b->down, ndims - 1);
if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_a->high, tmp_spans) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(tmp_spans);
}
if(span_a->high < span_b->high) {
if(NULL == (tmp_span = H5S__hyper_new_span(span_a->high + 1, span_b->high, span_b->down, span_b->next)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, tmp_span);
recover_b = TRUE;
}
else {
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
}
else if(span_a->low < span_b->low && span_a->high > span_b->high) {
if(H5S__hyper_cmp_spans(span_a->down, span_b->down)) {
if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_b->high, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
}
else {
if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_b->low - 1, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
tmp_spans = H5S__hyper_merge_spans_helper(span_a->down, span_b->down, ndims - 1);
if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_b->high, tmp_spans) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(tmp_spans);
}
if(NULL == (tmp_span = H5S__hyper_new_span(span_b->high + 1, span_a->high, span_a->down, span_a->next)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, tmp_span);
recover_a = TRUE;
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
else if(span_a->low >= span_b->low && span_a->high <= span_b->high) {
if(H5S__hyper_cmp_spans(span_a->down, span_b->down)) {
if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_a->high, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
}
else {
if(span_a->low > span_b->low) {
if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_a->low - 1, span_b->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
}
else {
}
tmp_spans = H5S__hyper_merge_spans_helper(span_a->down, span_b->down, ndims - 1);
if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_a->high, tmp_spans) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(tmp_spans);
}
if(span_a->high < span_b->high) {
if(NULL == (tmp_span = H5S__hyper_new_span(span_a->high + 1, span_b->high, span_b->down, span_b->next)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, tmp_span);
recover_b = TRUE;
}
else {
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
}
else if((span_a->low >= span_b->low && span_a->low <= span_b->high) && span_a->high > span_b->high) {
if(H5S__hyper_cmp_spans(span_a->down, span_b->down)) {
if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_b->high, span_b->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
}
else {
if(span_a->low > span_b->low) {
if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_a->low - 1, span_b->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
}
else {
}
tmp_spans = H5S__hyper_merge_spans_helper(span_a->down, span_b->down, ndims - 1);
if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_b->high, tmp_spans) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(tmp_spans);
}
if(NULL == (tmp_span = H5S__hyper_new_span(span_b->high + 1, span_a->high, span_a->down, span_a->next)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, tmp_span);
recover_a = TRUE;
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
else {
if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_b->high, span_b->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
}
if(span_a != NULL && span_b == NULL) {
while(span_a != NULL) {
if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_a->high, span_a->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
}
}
if(span_a == NULL && span_b != NULL) {
while(span_b != NULL) {
if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_b->high, span_b->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
}
}
}
ret_value = merged_spans;
done:
if(ret_value == NULL)
if(merged_spans)
H5S__hyper_free_span_info(merged_spans);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space);
HDassert(new_spans);
if(space->select.sel_info.hslab->span_lst == NULL) {
space->select.sel_info.hslab->span_lst = new_spans;
space->select.sel_info.hslab->span_lst->count++;
}
else {
H5S_hyper_span_info_t *merged_spans;
if(NULL == (merged_spans = H5S__hyper_merge_spans_helper(space->select.sel_info.hslab->span_lst, new_spans, space->extent.rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTMERGE, FAIL, "can't merge hyperslab spans")
H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst);
space->select.sel_info.hslab->span_lst = merged_spans;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static hsize_t
H5S__hyper_spans_nelem_helper(H5S_hyper_span_info_t *spans, unsigned op_info_i,
uint64_t op_gen)
{
hsize_t ret_value = 0;
FUNC_ENTER_STATIC_NOERR
HDassert(spans);
if(spans->op_info[op_info_i].op_gen == op_gen)
ret_value = spans->op_info[op_info_i].u.nelmts;
else {
const H5S_hyper_span_t *span;
span = spans->head;
if(NULL == span->down) {
while(span != NULL) {
ret_value += (span->high - span->low) + 1;
span = span->next;
}
}
else {
while(span != NULL) {
hsize_t nelmts;
nelmts = (span->high - span->low) + 1;
ret_value += nelmts * H5S__hyper_spans_nelem_helper(span->down, op_info_i, op_gen);
span = span->next;
}
}
spans->op_info[op_info_i].op_gen = op_gen;
spans->op_info[op_info_i].u.nelmts = ret_value;
}
FUNC_LEAVE_NOAPI(ret_value)
}
static hsize_t
H5S__hyper_spans_nelem(H5S_hyper_span_info_t *spans)
{
uint64_t op_gen;
hsize_t ret_value = 0;
FUNC_ENTER_STATIC_NOERR
HDassert(spans);
op_gen = H5S__hyper_get_op_gen();
ret_value = H5S__hyper_spans_nelem_helper(spans, 0, op_gen);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_add_disjoint_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space);
HDassert(new_spans);
space->select.num_elem += H5S__hyper_spans_nelem(new_spans);
if(H5S__hyper_merge_spans(space, new_spans) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't merge hyperslabs")
H5S__hyper_free_span_info(new_spans);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
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)
{
H5S_hyper_span_info_t *down = NULL;
H5S_hyper_span_t *last_span;
H5S_hyper_span_t *head = NULL;
int i;
H5S_hyper_span_info_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(rank > 0);
HDassert(start);
HDassert(stride);
HDassert(count);
HDassert(block);
for(i = (int)(rank - 1); i >= 0; i--) {
hsize_t curr_low, curr_high;
hsize_t dim_stride;
unsigned u;
if(0 == count[i])
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, NULL, "count == 0 is invalid")
head = NULL;
last_span = NULL;
curr_low = start[i];
curr_high = start[i] + (block[i] - 1);
dim_stride = stride[i];
for(u = 0; u < count[i]; u++, curr_low += dim_stride, curr_high += dim_stride) {
H5S_hyper_span_t *span;
if(NULL == (span = H5FL_MALLOC(H5S_hyper_span_t)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
span->low = curr_low;
span->high = curr_high;
span->next = NULL;
span->down = down;
if(head == NULL)
head = span;
else
last_span->next = span;
last_span = span;
}
if(down != NULL)
down->count = (unsigned)count[i];
if(NULL == (down = H5S__hyper_new_span_info(rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
down->head = head;
down->tail = last_span;
down->low_bounds[0] = down->head->low;
down->high_bounds[0] = down->tail->high;
if(head->down) {
H5MM_memcpy(&down->low_bounds[1], &head->down->low_bounds[0], sizeof(hsize_t) * ((rank - 1) - (unsigned)i));
H5MM_memcpy(&down->high_bounds[1], &head->down->high_bounds[0], sizeof(hsize_t) * ((rank - 1) - (unsigned)i));
}
}
if(down)
down->count = 1;
ret_value = down;
done:
if(!ret_value) {
if(head || down) {
if(head && down)
if(down->head != head)
down = NULL;
do {
if(down) {
head = down->head;
down = (H5S_hyper_span_info_t *)H5FL_ARR_FREE(hbounds_t, down);
}
down = head->down;
while(head) {
last_span = head->next;
head = H5FL_FREE(H5S_hyper_span_t, head);
head = last_span;
}
} while(down);
}
}
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_update_diminfo(H5S_t *space, H5S_seloper_t op,
const H5S_hyper_dim_t *new_hyper_diminfo)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_NOERR
HDassert(space);
HDassert(new_hyper_diminfo);
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;
else {
H5S_hyper_dim_t tmp_diminfo[H5S_MAX_RANK];
hbool_t found_nonidentical_dim = FALSE;
unsigned curr_dim;
H5MM_memcpy(tmp_diminfo, space->select.sel_info.hslab->diminfo.opt, sizeof(tmp_diminfo));
for(curr_dim = 0; curr_dim < space->extent.rank; curr_dim++) {
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;
if(found_nonidentical_dim) {
space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
break;
}
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;
}
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;
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;
}
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;
}
if((tmp_diminfo[curr_dim].count == 1) && (high_count == 1)) {
if((tmp_diminfo[curr_dim].start + tmp_diminfo[curr_dim].block)
> high_start) {
if(op == H5S_SELECT_OR)
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 {
if(tmp_diminfo[curr_dim].block != high_block) {
space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
break;
}
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;
}
}
else if((tmp_diminfo[curr_dim].start + tmp_diminfo[curr_dim].block)
== high_start)
tmp_diminfo[curr_dim].block += high_block;
else {
if(tmp_diminfo[curr_dim].block != high_block) {
space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
break;
}
tmp_diminfo[curr_dim].stride = high_start - tmp_diminfo[curr_dim].start;
tmp_diminfo[curr_dim].count = 2;
}
}
else {
if(tmp_diminfo[curr_dim].block != new_hyper_diminfo[curr_dim].block) {
space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
break;
}
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;
}
if(op == H5S_SELECT_OR) {
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;
}
}
else
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;
}
tmp_diminfo[curr_dim].count = ((high_start
- tmp_diminfo[curr_dim].start)
/ tmp_diminfo[curr_dim].stride) + high_count;
}
found_nonidentical_dim = TRUE;
}
}
if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES)
for(curr_dim = 0; curr_dim < space->extent.rank; curr_dim++) {
hsize_t tmp_high_bound;
space->select.sel_info.hslab->diminfo.app[curr_dim].start = space->select.sel_info.hslab->diminfo.opt[curr_dim].start = tmp_diminfo[curr_dim].start;
HDassert(tmp_diminfo[curr_dim].stride > 0);
space->select.sel_info.hslab->diminfo.app[curr_dim].stride = space->select.sel_info.hslab->diminfo.opt[curr_dim].stride = tmp_diminfo[curr_dim].stride;
HDassert(tmp_diminfo[curr_dim].count > 0);
space->select.sel_info.hslab->diminfo.app[curr_dim].count = space->select.sel_info.hslab->diminfo.opt[curr_dim].count = tmp_diminfo[curr_dim].count;
HDassert(tmp_diminfo[curr_dim].block > 0);
space->select.sel_info.hslab->diminfo.app[curr_dim].block = space->select.sel_info.hslab->diminfo.opt[curr_dim].block = tmp_diminfo[curr_dim].block;
if(tmp_diminfo[curr_dim].start < space->select.sel_info.hslab->diminfo.low_bounds[curr_dim])
space->select.sel_info.hslab->diminfo.low_bounds[curr_dim] = tmp_diminfo[curr_dim].start;
tmp_high_bound = tmp_diminfo[curr_dim].start +
(tmp_diminfo[curr_dim].block - 1) +
(tmp_diminfo[curr_dim].stride * (tmp_diminfo[curr_dim].count - 1));
if(tmp_high_bound > space->select.sel_info.hslab->diminfo.low_bounds[curr_dim])
space->select.sel_info.hslab->diminfo.high_bounds[curr_dim] = tmp_high_bound;
}
}
FUNC_LEAVE_NOAPI(ret_value)
}
static hbool_t
H5S__hyper_rebuild_helper(const H5S_hyper_span_info_t *spans, H5S_hyper_dim_t span_slab_info[])
{
const H5S_hyper_span_t *span;
const H5S_hyper_span_t *prev_span;
hsize_t start;
hsize_t stride;
hsize_t block;
hsize_t prev_low;
size_t spancount;
hbool_t ret_value = TRUE;
FUNC_ENTER_STATIC_NOERR
HDassert(spans);
span = spans->head;
stride = 1;
prev_low = 0;
spancount = 0;
if(span->down)
if(!H5S__hyper_rebuild_helper(span->down, &span_slab_info[1]))
HGOTO_DONE(FALSE)
start = span->low;
block = (span->high - span->low) + 1;
prev_span = NULL;
while(span) {
if(spancount > 0) {
hsize_t curr_stride;
hsize_t curr_block;
HDassert(prev_span);
if(span->down && prev_span->down != span->down)
if(!H5S__hyper_cmp_spans(span->down, prev_span->down))
HGOTO_DONE(FALSE)
curr_stride = span->low - prev_low;
curr_block = (span->high - span->low) + 1;
if(curr_block != block)
HGOTO_DONE(FALSE)
if(spancount > 1) {
if(stride != curr_stride)
HGOTO_DONE(FALSE)
}
else
stride = curr_stride;
}
prev_low = span->low;
prev_span = span;
span = span->next;
spancount++;
}
span_slab_info[0].start = start;
span_slab_info[0].count = spancount;
span_slab_info[0].block = block;
span_slab_info[0].stride = stride;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void
H5S__hyper_rebuild(H5S_t *space)
{
H5S_hyper_dim_t rebuilt_slab_info[H5S_MAX_RANK];
FUNC_ENTER_PACKAGE_NOERR
HDassert(space);
HDassert(space->select.sel_info.hslab->span_lst);
if(FALSE == H5S__hyper_rebuild_helper(space->select.sel_info.hslab->span_lst, rebuilt_slab_info))
space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_IMPOSSIBLE;
else {
H5MM_memcpy(space->select.sel_info.hslab->diminfo.app, rebuilt_slab_info, sizeof(rebuilt_slab_info));
H5MM_memcpy(space->select.sel_info.hslab->diminfo.opt, rebuilt_slab_info, sizeof(rebuilt_slab_info));
H5MM_memcpy(space->select.sel_info.hslab->diminfo.low_bounds, space->select.sel_info.hslab->span_lst->low_bounds, sizeof(hsize_t) * space->extent.rank);
H5MM_memcpy(space->select.sel_info.hslab->diminfo.high_bounds, space->select.sel_info.hslab->span_lst->high_bounds, sizeof(hsize_t) * space->extent.rank);
space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
}
FUNC_LEAVE_NOAPI_VOID
}
static herr_t
H5S__hyper_generate_spans(H5S_t *space)
{
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;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space);
HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
for(u = 0; u < space->extent.rank; u++) {
if(space->select.sel_info.hslab->diminfo.opt[u].count == H5S_UNLIMITED)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "can't generate spans with unlimited count")
if(space->select.sel_info.hslab->diminfo.opt[u].block == H5S_UNLIMITED)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "can't generate spans with unlimited block")
tmp_start[u] = space->select.sel_info.hslab->diminfo.opt[u].start;
tmp_stride[u] = space->select.sel_info.hslab->diminfo.opt[u].stride;
tmp_count[u] = space->select.sel_info.hslab->diminfo.opt[u].count;
tmp_block[u] = space->select.sel_info.hslab->diminfo.opt[u].block;
}
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)
}
static H5_ATTR_PURE hbool_t
H5S__check_spans_overlap(const H5S_hyper_span_info_t *spans1,
const H5S_hyper_span_info_t *spans2)
{
hbool_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(spans1);
HDassert(spans2);
if(H5S_RANGE_OVERLAP(spans1->low_bounds[0], spans1->high_bounds[0],
spans2->low_bounds[0], spans2->high_bounds[0])) {
H5S_hyper_span_t *span1, *span2;
span1 = spans1->head;
span2 = spans2->head;
while(span1 && span2) {
if(H5S_RANGE_OVERLAP(span1->low, span1->high, span2->low, span2->high)) {
if(span1->down) {
HDassert(span2->down);
if(H5S__check_spans_overlap(span1->down, span2->down))
HGOTO_DONE(TRUE);
}
else
HGOTO_DONE(TRUE);
}
if(span1->high <= span2->high) {
if(NULL == span1->next && NULL != span2->next)
span2 = span2->next;
else
span1 = span1->next;
}
else {
if(NULL == span2->next && NULL != span1->next)
span1 = span1->next;
else
span2 = span2->next;
}
}
HDassert((NULL == span1 && (NULL != span2 && NULL == span2->next)) ||
((NULL != span1 && NULL == span1->next) && NULL == span2));
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__fill_in_new_space(H5S_t *space1, H5S_seloper_t op,
H5S_hyper_span_info_t *space2_span_lst, 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;
H5S_hyper_span_info_t *a_and_b = NULL;
H5S_hyper_span_info_t *b_not_a = NULL;
hbool_t overlapped = FALSE;
hbool_t is_result_new = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space1);
HDassert(space2_span_lst);
HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
HDassert(*result == NULL || *result == space1);
HDassert(space1->select.sel_info.hslab->span_lst);
HDassert(span2_owned);
*span2_owned = FALSE;
*updated_spans = FALSE;
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;
}
overlapped = H5S__check_spans_overlap(space1->select.sel_info.hslab->span_lst, space2_span_lst);
if(!overlapped) {
switch(op) {
case H5S_SELECT_OR:
case H5S_SELECT_XOR:
if(is_result_new)
(*result)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(space1->select.sel_info.hslab->span_lst, space1->extent.rank);
if(!can_own_span2) {
b_not_a = H5S__hyper_copy_span(space2_span_lst, space1->extent.rank);
if(H5S__hyper_add_disjoint_spans(*result, b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't append hyperslabs")
b_not_a = NULL;
}
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;
}
*updated_spans = TRUE;
break;
case H5S_SELECT_AND:
if(H5S_select_none(*result) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
HGOTO_DONE(SUCCEED);
case H5S_SELECT_NOTB:
if(is_result_new)
(*result)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(space1->select.sel_info.hslab->span_lst, space1->extent.rank);
*updated_spans = TRUE;
break;
case H5S_SELECT_NOTA:
if(!is_result_new) {
HDassert(space1 == *result);
H5S__hyper_free_span_info(space1->select.sel_info.hslab->span_lst);
space1->select.sel_info.hslab->span_lst = NULL;
}
if(!can_own_span2)
(*result)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(space2_span_lst, space1->extent.rank);
else {
(*result)->select.sel_info.hslab->span_lst = space2_span_lst;
*span2_owned = TRUE;
}
(*result)->select.num_elem = H5S__hyper_spans_nelem(space2_span_lst);
*updated_spans = TRUE;
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")
}
}
else {
unsigned selector = 0;
switch(op) {
case H5S_SELECT_OR:
selector = H5S_HYPER_COMPUTE_B_NOT_A;
break;
case H5S_SELECT_XOR:
selector = H5S_HYPER_COMPUTE_A_NOT_B | H5S_HYPER_COMPUTE_B_NOT_A;
break;
case H5S_SELECT_AND:
selector = H5S_HYPER_COMPUTE_A_AND_B;
break;
case H5S_SELECT_NOTB:
selector = H5S_HYPER_COMPUTE_A_NOT_B;
break;
case H5S_SELECT_NOTA:
selector = H5S_HYPER_COMPUTE_B_NOT_A;
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")
}
if(H5S__hyper_clip_spans(space1->select.sel_info.hslab->span_lst,
space2_span_lst, selector, space1->extent.rank,
&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, space1->extent.rank);
break;
case H5S_SELECT_AND:
case H5S_SELECT_XOR:
case H5S_SELECT_NOTB:
case H5S_SELECT_NOTA:
if(!is_result_new) {
HDassert(space1 == *result);
H5S__hyper_free_span_info(space1->select.sel_info.hslab->span_lst);
space1->select.sel_info.hslab->span_lst = NULL;
}
(*result)->select.num_elem = 0;
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")
}
if(a_not_b) {
HDassert(NULL == (*result)->select.sel_info.hslab->span_lst);
(*result)->select.sel_info.hslab->span_lst = a_not_b;
(*result)->select.num_elem = H5S__hyper_spans_nelem(a_not_b);
*updated_spans = TRUE;
a_not_b = NULL;
}
if(a_and_b) {
HDassert(NULL == (*result)->select.sel_info.hslab->span_lst);
(*result)->select.sel_info.hslab->span_lst = a_and_b;
(*result)->select.num_elem = H5S__hyper_spans_nelem(a_and_b);
*updated_spans = TRUE;
a_and_b = NULL;
}
if(b_not_a) {
if(H5S__hyper_merge_spans(*result, b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
(*result)->select.num_elem += H5S__hyper_spans_nelem(b_not_a);
*updated_spans = TRUE;
}
}
if(!*updated_spans) {
if(H5S_SELECT_OR != op) {
if(H5S_select_none(*result) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
}
}
done:
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);
FUNC_LEAVE_NOAPI(ret_value)
}
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;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space);
HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID);
HDassert(start);
HDassert(stride);
HDassert(count);
HDassert(block);
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")
if(op == H5S_SELECT_SET) {
if(NULL != space->select.sel_info.hslab->span_lst)
H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst);
space->select.sel_info.hslab->span_lst = new_spans;
space->select.num_elem = H5S__hyper_spans_nelem(new_spans);
new_spans = NULL;
}
else {
hbool_t new_spans_owned = FALSE;
hbool_t updated_spans = FALSE;
if(H5S__fill_in_new_space(space, op, new_spans, TRUE, &new_spans_owned, &updated_spans, &space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't generate the specified hyperslab")
if(updated_spans) {
H5S_hyper_dim_t new_hyper_diminfo[H5S_MAX_RANK];
unsigned u;
HDassert(space->select.sel_info.hslab->span_lst->head);
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];
}
if(H5S__hyper_update_diminfo(space, op, new_hyper_diminfo) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't update hyperslab info")
}
if(new_spans_owned)
new_spans = NULL;
}
done:
if(new_spans)
H5S__hyper_free_span_info(new_spans);
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5S__set_regular_hyperslab(H5S_t *space, const hsize_t start[],
const hsize_t *app_stride, const hsize_t app_count[], const hsize_t *app_block,
const hsize_t *opt_stride, const hsize_t opt_count[], const hsize_t *opt_block)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space);
HDassert(start);
HDassert(app_stride);
HDassert(app_count);
HDassert(app_block);
HDassert(opt_stride);
HDassert(opt_count);
HDassert(opt_block);
if(H5S_SELECT_RELEASE(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
if(NULL == (space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info")
space->select.num_elem = 1;
space->select.sel_info.hslab->unlim_dim = -1;
for(u = 0; u < space->extent.rank; u++) {
space->select.sel_info.hslab->diminfo.app[u].start = start[u];
space->select.sel_info.hslab->diminfo.app[u].stride = app_stride[u];
space->select.sel_info.hslab->diminfo.app[u].count = app_count[u];
space->select.sel_info.hslab->diminfo.app[u].block = app_block[u];
space->select.sel_info.hslab->diminfo.opt[u].start = start[u];
space->select.sel_info.hslab->diminfo.opt[u].stride = opt_stride[u];
space->select.sel_info.hslab->diminfo.opt[u].count = opt_count[u];
space->select.sel_info.hslab->diminfo.opt[u].block = opt_block[u];
space->select.num_elem *= (opt_count[u] * opt_block[u]);
space->select.sel_info.hslab->diminfo.low_bounds[u] = start[u];
if((app_count[u] == H5S_UNLIMITED) || (app_block[u] == H5S_UNLIMITED)) {
space->select.sel_info.hslab->unlim_dim = (int)u;
space->select.sel_info.hslab->diminfo.high_bounds[u] = H5S_UNLIMITED;
}
else
space->select.sel_info.hslab->diminfo.high_bounds[u] = start[u] + opt_stride[u] * (opt_count[u] - 1) + (opt_block[u] - 1);
}
if(space->select.sel_info.hslab->unlim_dim >= 0) {
space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
for(u = 0; u < space->extent.rank; u++)
if((int)u != space->select.sel_info.hslab->unlim_dim)
space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
space->select.num_elem = H5S_UNLIMITED;
}
space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
space->select.sel_info.hslab->span_lst = NULL;
space->select.type = H5S_sel_hyper;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_regular_and_single_block(H5S_t *space, const hsize_t start[],
const hsize_t block[])
{
hsize_t select_end, block_end;
hbool_t single_block;
hbool_t overlap;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space);
HDassert(start);
HDassert(block);
single_block = TRUE;
for(u = 0; u < space->extent.rank; u++)
if(1 != space->select.sel_info.hslab->diminfo.opt[u].count) {
single_block = FALSE;
break;
}
if(single_block) {
hsize_t new_start[H5S_MAX_RANK];
hsize_t new_block[H5S_MAX_RANK];
overlap = TRUE;
for(u = 0; u < space->extent.rank; u++) {
select_end = space->select.sel_info.hslab->diminfo.high_bounds[u];
block_end = (start[u] + block[u]) - 1;
if(!H5S_RANGE_OVERLAP(space->select.sel_info.hslab->diminfo.opt[u].start, select_end, start[u], block_end)) {
overlap = FALSE;
break;
}
new_start[u] = MAX(space->select.sel_info.hslab->diminfo.opt[u].start, start[u]);
new_block[u] = (MIN(select_end, block_end) - new_start[u]) + 1;
}
if(overlap) {
if(H5S__set_regular_hyperslab(space, new_start, H5S_hyper_ones_g, H5S_hyper_ones_g, new_block,
H5S_hyper_ones_g, H5S_hyper_ones_g, new_block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't set regular hyperslab selection")
}
else
if(H5S_select_none(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
}
else {
hsize_t new_start[H5S_MAX_RANK];
hsize_t new_count[H5S_MAX_RANK];
hsize_t stride[H5S_MAX_RANK];
hsize_t new_block[H5S_MAX_RANK];
hbool_t partial_first_span;
hbool_t partial_last_span;
overlap = TRUE;
partial_first_span = FALSE;
partial_last_span = FALSE;
for(u = 0; u < space->extent.rank; u++) {
hsize_t first_span_start, first_span_end;
hsize_t last_span_start, last_span_end;
hsize_t nstride;
select_end = space->select.sel_info.hslab->diminfo.high_bounds[u];
block_end = (start[u] + block[u]) - 1;
if(!H5S_RANGE_OVERLAP(space->select.sel_info.hslab->diminfo.opt[u].start, select_end, start[u], block_end)) {
overlap = FALSE;
break;
}
if(space->select.sel_info.hslab->diminfo.opt[u].start >= start[u]) {
first_span_start = space->select.sel_info.hslab->diminfo.opt[u].start;
first_span_end = (first_span_start +
space->select.sel_info.hslab->diminfo.opt[u].block) - 1;
if(block_end >= first_span_start && block_end <= first_span_end)
partial_first_span = TRUE;
}
else {
hsize_t adj_start;
adj_start = start[u] - space->select.sel_info.hslab->diminfo.opt[u].start;
if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
nstride = adj_start / space->select.sel_info.hslab->diminfo.opt[u].stride;
else
nstride = 0;
first_span_start = space->select.sel_info.hslab->diminfo.opt[u].start +
(nstride * space->select.sel_info.hslab->diminfo.opt[u].stride);
first_span_end = (first_span_start +
space->select.sel_info.hslab->diminfo.opt[u].block) - 1;
if(first_span_start < start[u] && first_span_end >= start[u])
partial_first_span = TRUE;
if(first_span_end < start[u]) {
first_span_start += space->select.sel_info.hslab->diminfo.opt[u].stride;
first_span_end += space->select.sel_info.hslab->diminfo.opt[u].stride;
}
}
if(select_end < block_end) {
last_span_start = (select_end -
space->select.sel_info.hslab->diminfo.opt[u].block) + 1;
last_span_end = select_end;
if(start[u] >= last_span_start && start[u] <= last_span_end)
partial_last_span = TRUE;
}
else {
hsize_t adj_end;
adj_end = block_end - space->select.sel_info.hslab->diminfo.opt[u].start;
if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
nstride = adj_end / space->select.sel_info.hslab->diminfo.opt[u].stride;
else
nstride = 0;
last_span_start = space->select.sel_info.hslab->diminfo.opt[u].start +
(nstride * space->select.sel_info.hslab->diminfo.opt[u].stride);
last_span_end = (last_span_start +
space->select.sel_info.hslab->diminfo.opt[u].block) - 1;
if(block_end >= last_span_start && block_end <= last_span_end)
partial_last_span = TRUE;
}
if(last_span_end < start[u]) {
overlap = FALSE;
break;
}
HDassert(first_span_start <= last_span_start);
new_start[u] = first_span_start;
if(last_span_start != first_span_start)
new_count[u] = ((last_span_start - first_span_start) /
space->select.sel_info.hslab->diminfo.opt[u].stride) + 1;
else
new_count[u] = 1;
new_block[u] = space->select.sel_info.hslab->diminfo.opt[u].block;
stride[u] = space->select.sel_info.hslab->diminfo.opt[u].stride;
}
if(overlap) {
if(H5S__set_regular_hyperslab(space, new_start, stride, new_count, new_block,
stride, new_count, new_block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't set regular hyperslab selection")
if(partial_first_span || partial_last_span) {
if(H5S__hyper_generate_spans(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
if(H5S__generate_hyperslab(space, H5S_SELECT_AND, start, H5S_hyper_ones_g, H5S_hyper_ones_g, block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs")
}
}
else {
if(H5S_select_none(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
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[H5S_MAX_RANK];
hsize_t int_count[H5S_MAX_RANK];
hsize_t int_block[H5S_MAX_RANK];
const hsize_t *opt_stride;
const hsize_t *opt_count;
const hsize_t *opt_block;
int unlim_dim = -1;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space);
HDassert(start);
HDassert(count);
HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID);
if(stride == NULL)
stride = H5S_hyper_ones_g;
if(block == NULL)
block = H5S_hyper_ones_g;
for(u = 0; u < space->extent.rank; u++) {
if(count[u] > 1 && stride[u] < block[u])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab blocks overlap")
if(count[u] == 0 || block[u] == 0) {
switch(op) {
case H5S_SELECT_SET:
case H5S_SELECT_AND:
case H5S_SELECT_NOTA:
if(H5S_select_none(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
HGOTO_DONE(SUCCEED);
case H5S_SELECT_OR:
case H5S_SELECT_XOR:
case H5S_SELECT_NOTB:
HGOTO_DONE(SUCCEED);
case H5S_SELECT_NOOP:
case H5S_SELECT_APPEND:
case H5S_SELECT_PREPEND:
case H5S_SELECT_INVALID:
default:
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
}
}
if((count[u] == H5S_UNLIMITED) || (block[u] == H5S_UNLIMITED)) {
if(unlim_dim >= 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
else {
if(count[u] == block[u])
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited")
unlim_dim = (int)u;
}
}
}
if(stride == H5S_hyper_ones_g && block == H5S_hyper_ones_g) {
opt_stride = H5S_hyper_ones_g;
opt_count = H5S_hyper_ones_g;
opt_block = count;
}
else {
opt_stride = int_stride;
opt_count = int_count;
opt_block = int_block;
for(u = 0; u < space->extent.rank; u++) {
if((stride[u] == block[u]) && (count[u] != H5S_UNLIMITED)) {
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];
}
else {
if(count[u] == 1)
int_stride[u] = 1;
else {
HDassert((stride[u] > block[u]) ||
((stride[u] == block[u]) && (count[u] == H5S_UNLIMITED)));
int_stride[u] = stride[u];
}
int_count[u] = count[u];
int_block[u] = block[u];
}
}
}
if((H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS)
&& (space->select.sel_info.hslab->unlim_dim >= 0)
&& (op != H5S_SELECT_SET)) {
if(unlim_dim >= 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection with another unlimited selection")
if(!((op == H5S_SELECT_AND) || (op == H5S_SELECT_NOTA)))
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported operation on unlimited selection")
HDassert(space->select.sel_info.hslab->diminfo_valid);
if(H5S_hyper_clip_unlim(space,
start[space->select.sel_info.hslab->unlim_dim]
+ ((opt_count[space->select.sel_info.hslab->unlim_dim] - (hsize_t)1)
* opt_stride[space->select.sel_info.hslab->unlim_dim])
+ opt_block[space->select.sel_info.hslab->unlim_dim]) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection")
HDassert((space->select.num_elem > (hsize_t)0) || (space->select.type->type == H5S_SEL_NONE));
}
switch(H5S_GET_SELECT_TYPE(space)) {
case H5S_SEL_NONE:
switch(op) {
case H5S_SELECT_SET:
break;
case H5S_SELECT_OR:
case H5S_SELECT_XOR:
case H5S_SELECT_NOTA:
op = H5S_SELECT_SET;
break;
case H5S_SELECT_AND:
case H5S_SELECT_NOTB:
HGOTO_DONE(SUCCEED);
case H5S_SELECT_NOOP:
case H5S_SELECT_APPEND:
case H5S_SELECT_PREPEND:
case H5S_SELECT_INVALID:
default:
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
}
break;
case H5S_SEL_ALL:
switch(op) {
case H5S_SELECT_SET:
break;
case H5S_SELECT_OR:
HGOTO_DONE(SUCCEED);
case H5S_SELECT_AND:
op = H5S_SELECT_SET;
break;
case H5S_SELECT_XOR:
case H5S_SELECT_NOTB:
{
const hsize_t *tmp_start;
const hsize_t *tmp_stride;
const hsize_t *tmp_count;
const hsize_t *tmp_block;
tmp_start = H5S_hyper_zeros_g;
tmp_stride = tmp_count = H5S_hyper_ones_g;
tmp_block = space->extent.size;
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")
}
break;
case H5S_SELECT_NOTA:
if(H5S_select_none(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
HGOTO_DONE(SUCCEED);
case H5S_SELECT_NOOP:
case H5S_SELECT_APPEND:
case H5S_SELECT_PREPEND:
case H5S_SELECT_INVALID:
default:
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
}
break;
case H5S_SEL_HYPERSLABS:
break;
case H5S_SEL_POINTS:
if(op == H5S_SELECT_SET)
break;
H5_ATTR_FALLTHROUGH
case H5S_SEL_ERROR:
case H5S_SEL_N:
default:
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
}
if(op == H5S_SELECT_SET) {
if(H5S__set_regular_hyperslab(space, start, stride, count, block, opt_stride, opt_count, opt_block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't set regular hyperslab selection")
}
else if(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA) {
hbool_t single_block;
HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
if(unlim_dim >= 0) {
hsize_t bounds_start[H5S_MAX_RANK];
hsize_t bounds_end[H5S_MAX_RANK];
hsize_t tmp_count = opt_count[unlim_dim];
hsize_t tmp_block = opt_block[unlim_dim];
if(space->select.sel_info.hslab->unlim_dim >= 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection with another unlimited selection")
if(!((op == H5S_SELECT_AND) || (op == H5S_SELECT_NOTB)))
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported operation with unlimited selection")
if(H5S__hyper_bounds(space, bounds_start, bounds_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds")
H5S__hyper_get_clip_diminfo(start[unlim_dim], opt_stride[unlim_dim], &tmp_count, &tmp_block, bounds_end[unlim_dim] + (hsize_t)1);
HDassert((tmp_count == 1) || (opt_count != H5S_hyper_ones_g));
HDassert((tmp_block == 1) || (opt_block != H5S_hyper_ones_g));
if(opt_count != H5S_hyper_ones_g) {
HDassert(opt_count == int_count);
int_count[unlim_dim] = tmp_count;
}
if(opt_block != H5S_hyper_ones_g) {
HDassert(opt_block == int_block);
int_block[unlim_dim] = tmp_block;
}
}
single_block = TRUE;
for(u = 0; u < space->extent.rank; u++)
if(1 != opt_count[u]) {
single_block = FALSE;
break;
}
if(H5S_SELECT_AND == op && single_block &&
space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
if(H5S__hyper_regular_and_single_block(space, start, opt_block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTOPERATE, FAIL, "can't 'AND' single block against regular hyperslab")
}
else {
if(NULL == space->select.sel_info.hslab->span_lst)
if(H5S__hyper_generate_spans(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
space->select.type = H5S_sel_hyper;
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")
}
}
else
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
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[])
{
H5S_t *space;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE6("e", "iSs*h*h*h*h", space_id, op, start, stride, count, block);
if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
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))
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;
for(u = 0; u < space->extent.rank; u++)
if(stride[u] == 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid stride==0 value")
}
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)
}
herr_t
H5S_combine_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)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(old_space);
HDassert(start);
HDassert(count);
HDassert(op >= H5S_SELECT_SET && op <= H5S_SELECT_NOTA);
HDassert(new_space);
HDassert(*new_space == NULL);
if(stride == NULL)
stride = H5S_hyper_ones_g;
if(block == NULL)
block = H5S_hyper_ones_g;
for(u = 0; u < old_space->extent.rank; u++) {
if(count[u] > 1 && stride[u] < block[u])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab blocks overlap")
if(count[u] == 0 || block[u] == 0) {
switch(op) {
case H5S_SELECT_AND:
case H5S_SELECT_NOTA:
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:
case H5S_SELECT_XOR:
case H5S_SELECT_NOTB:
if(NULL == ((*new_space) = H5S_copy(old_space, FALSE, TRUE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace")
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")
}
}
}
if(H5S_GET_SELECT_TYPE(old_space) == H5S_SEL_HYPERSLABS) {
hsize_t *old_low_bounds;
hsize_t *old_high_bounds;
hsize_t new_low_bounds[H5S_MAX_RANK];
hsize_t new_high_bounds[H5S_MAX_RANK];
hbool_t overlapped = FALSE;
if(old_space->select.sel_info.hslab->span_lst) {
old_low_bounds = old_space->select.sel_info.hslab->span_lst->low_bounds;
old_high_bounds = old_space->select.sel_info.hslab->span_lst->high_bounds;
}
else {
old_low_bounds = old_space->select.sel_info.hslab->diminfo.low_bounds;
old_high_bounds = old_space->select.sel_info.hslab->diminfo.high_bounds;
}
for(u = 0; u < old_space->extent.rank; u++) {
new_low_bounds[u] = start[u];
new_high_bounds[u] = start[u] + stride[u] * (count[u] - 1) + (block[u] - 1);
}
if(H5S_RANGE_OVERLAP(old_low_bounds[0], old_high_bounds[0],
new_low_bounds[0], new_high_bounds[0]))
overlapped = TRUE;
if(!overlapped) {
H5S_hyper_span_info_t *new_spans = NULL;
H5S_hyper_dim_t new_hyper_diminfo[H5S_MAX_RANK];
if(NULL == ((*new_space) = H5S_copy(old_space, TRUE, TRUE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, 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;
}
switch(op) {
case H5S_SELECT_OR:
case H5S_SELECT_XOR:
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, old_space->extent.rank);
if(H5S__hyper_add_disjoint_spans(*new_space, new_spans) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't append hyperslabs")
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];
}
if(H5S__hyper_update_diminfo(*new_space, op, new_hyper_diminfo) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't update hyperslab info")
break;
case H5S_SELECT_AND:
if(H5S_select_none((*new_space)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
break;
case H5S_SELECT_NOTB:
if(NULL != old_space->select.sel_info.hslab->span_lst) {
if(NULL == ((*new_space)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(old_space->select.sel_info.hslab->span_lst, old_space->extent.rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy dataspace")
}
else {
if(H5S_select_none((*new_space)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
}
break;
case H5S_SELECT_NOTA:
if(H5S__set_regular_hyperslab(*new_space, start, stride, count, block, stride, count, block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't set regular selection")
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")
}
HGOTO_DONE(SUCCEED);
}
}
if(NULL == ((*new_space) = H5S_copy(old_space, TRUE, TRUE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace")
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)
}
static herr_t
H5S__fill_in_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2, H5S_t **result)
{
hbool_t span2_owned;
hbool_t updated_spans;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(space1);
HDassert(space2);
HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
HDassert(space1->extent.rank == space2->extent.rank);
HDassert(NULL == *result || *result == space1);
HDassert(space1->select.sel_info.hslab->span_lst);
HDassert(space2->select.sel_info.hslab->span_lst);
if(H5S__fill_in_new_space(space1, op, space2->select.sel_info.hslab->span_lst, FALSE, &span2_owned, &updated_spans, result) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create the specified selection")
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->diminfo.opt) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't update hyperslab info")
}
else
(*result)->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
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[])
{
H5S_t *space;
H5S_t *new_space = NULL;
hid_t ret_value;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE6("i", "iSs*h*h*h*h", space_id, op, start, stride, count, block);
if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
if(start == NULL || count == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "hyperslab not specified")
if(!(op >= H5S_SELECT_SET && op <= H5S_SELECT_NOTA))
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation")
if(H5S_combine_hyperslab(space, op, start, stride, count, block, &new_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to set hyperslab selection")
if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
done:
if(ret_value < 0 && new_space)
H5S_close(new_space);
FUNC_LEAVE_API(ret_value)
}
static H5S_t *
H5S__combine_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
{
H5S_t *new_space = NULL;
H5S_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(space1);
HDassert(space2);
HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
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(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->diminfo.opt[u].start;
tmp_stride[u] = space2->select.sel_info.hslab->diminfo.opt[u].stride;
tmp_count[u] = space2->select.sel_info.hslab->diminfo.opt[u].count;
tmp_block[u] = space2->select.sel_info.hslab->diminfo.opt[u].block;
}
if(H5S_combine_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")
}
else{
if(H5S__fill_in_select(space1, op, space2, &new_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, NULL, "can't clip hyperslab information")
}
new_space->select.sel_info.hslab->unlim_dim = -1;
ret_value = new_space;
done:
if(ret_value == NULL && new_space)
H5S_close(new_space);
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
{
H5S_t *space1;
H5S_t *space2;
H5S_t *new_space = NULL;
hid_t ret_value;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "iSsi", space1_id, op, space2_id);
if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA))
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation")
if(space1->extent.rank != space2->extent.rank)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces not same rank")
#if 0#endif
if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces don't have hyperslab selections")
if(NULL == (new_space = H5S__combine_select(space1, op, space2)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to create hyperslab selection")
if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
done:
if(ret_value < 0 && new_space)
H5S_close(new_space);
FUNC_LEAVE_API(ret_value)
}
herr_t
H5S__modify_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(space1);
HDassert(space2);
HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
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")
space1->select.sel_info.hslab->unlim_dim = -1;
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->diminfo.opt[u].start;
tmp_stride[u] = space2->select.sel_info.hslab->diminfo.opt[u].stride;
tmp_count[u] = space2->select.sel_info.hslab->diminfo.opt[u].count;
tmp_block[u] = space2->select.sel_info.hslab->diminfo.opt[u].block;
}
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")
}
else
if(H5S__fill_in_select(space1, op, space2, &space1) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't perform operation on two selections")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5Smodify_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
{
H5S_t *space1;
H5S_t *space2;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "iSsi", space1_id, op, space2_id);
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")
if(space1->extent.rank != space2->extent.rank)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same rank")
#if 0#endif
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")
if(H5S__modify_select(space1, op, space2) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to modify hyperslab selection")
done:
FUNC_LEAVE_API(ret_value)
}
static herr_t
H5S__hyper_proj_int_build_proj(H5S_hyper_project_intersect_ud_t *udata) {
H5S_hyper_span_info_t *copied_span_info = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(udata->nelem > 0);
if(udata->skip > 0) {
HDassert(udata->ds_span[udata->depth]);
do {
if(udata->ds_span[udata->depth]->down) {
if(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high) {
if(udata->skip < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, 0, udata->op_gen)
* (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
udata->ds_low[udata->depth] += udata->skip / udata->ds_span[udata->depth]->down->op_info[0].u.nelmts;
udata->skip %= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts;
break;
}
udata->skip -= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts
* (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1);
}
}
else {
HDassert(udata->ds_rank - udata->depth == 1);
HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high);
if(udata->skip < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
udata->ds_low[udata->depth] += udata->skip;
udata->skip = 0;
break;
}
udata->skip -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1;
}
udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
if(udata->ds_span[udata->depth])
udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
else if(udata->depth > 0) {
if(udata->ps_span_info[udata->depth]) {
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth - 1],
udata->ds_rank - udata->depth + 1, udata->ds_low[udata->depth - 1],
udata->ds_low[udata->depth - 1],
udata->ps_span_info[udata->depth]) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(udata->ps_span_info[udata->depth]);
udata->ps_span_info[udata->depth] = NULL;
}
udata->depth--;
HDassert(udata->ds_span[udata->depth]);
udata->ds_low[udata->depth]++;
}
else
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "insufficient elements in destination selection")
} while((udata->skip > 0)
|| (udata->ds_low[udata->depth] > udata->ds_span[udata->depth]->high));
HDassert(udata->ds_span[udata->depth]);
while(udata->skip > 0) {
HDassert(udata->ds_span[udata->depth]->down);
udata->depth++;
udata->ds_span[udata->depth] = udata->ds_span[udata->depth - 1]->down->head;
udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
if(udata->ds_span[udata->depth]->down) {
do {
if(udata->skip < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, 0, udata->op_gen)
* (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
udata->ds_low[udata->depth] += udata->skip / udata->ds_span[udata->depth]->down->op_info[0].u.nelmts;
udata->skip %= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts;
break;
}
udata->skip -= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts
* (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1);
udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
HDassert(udata->ds_span[udata->depth]);
udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
} while(udata->skip > 0);
}
else {
do {
if(udata->skip < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
udata->ds_low[udata->depth] += udata->skip;
udata->skip = 0;
break;
}
udata->skip -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1;
udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
HDassert(udata->ds_span[udata->depth]);
udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
} while(udata->skip > 0);
}
}
}
HDassert(udata->ds_span[udata->depth]);
do {
if(udata->ds_span[udata->depth]->down) {
if(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high) {
if(udata->nelem < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, 0, udata->op_gen)
* (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
if(udata->nelem >= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts) {
if(udata->share_selection) {
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->op_info[0].u.nelmts) - 1,
udata->ds_span[udata->depth]->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
if(NULL == (copied_span_info = H5S__hyper_copy_span_helper(udata->ds_span[udata->depth]->down, udata->ds_rank - udata->depth, 1, udata->op_gen)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination spans")
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->op_info[0].u.nelmts) - 1,
copied_span_info) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(copied_span_info);
copied_span_info = NULL;
}
udata->ds_low[udata->depth] += udata->nelem / udata->ds_span[udata->depth]->down->op_info[0].u.nelmts;
udata->nelem %= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts;
}
break;
}
if(udata->share_selection) {
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
udata->ds_span[udata->depth]->high,
udata->ds_span[udata->depth]->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
if(NULL == (copied_span_info = H5S__hyper_copy_span_helper(udata->ds_span[udata->depth]->down, udata->ds_rank - udata->depth, 1, udata->op_gen)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination spans")
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
udata->ds_span[udata->depth]->high,
copied_span_info) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(copied_span_info);
copied_span_info = NULL;
}
udata->nelem -= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts
* (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1);
}
}
else {
HDassert(udata->ds_rank - udata->depth == 1);
HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high);
if(udata->nelem < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1,
udata->ds_low[udata->depth], udata->ds_low[udata->depth] + udata->nelem - 1, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
udata->ds_low[udata->depth] += udata->nelem;
udata->nelem = 0;
break;
}
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1,
udata->ds_low[udata->depth], udata->ds_span[udata->depth]->high, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
udata->nelem -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1;
}
udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
if(udata->ds_span[udata->depth])
udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
else if(udata->depth > 0) {
HDassert(udata->ps_span_info[udata->depth]);
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth - 1],
udata->ds_rank - udata->depth + 1, udata->ds_low[udata->depth - 1],
udata->ds_low[udata->depth - 1],
udata->ps_span_info[udata->depth]) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(udata->ps_span_info[udata->depth]);
udata->ps_span_info[udata->depth] = NULL;
udata->depth--;
HDassert(udata->ds_span[udata->depth]);
udata->ds_low[udata->depth]++;
}
else {
if(udata->nelem > 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "insufficient elements in destination selection")
break;
}
} while((udata->nelem > 0)
|| (udata->ds_low[udata->depth] > udata->ds_span[udata->depth]->high));
HDassert(udata->ds_span[udata->depth] || (udata->nelem == 0));
while(udata->nelem > 0) {
HDassert(udata->ds_span[udata->depth]->down);
udata->depth++;
udata->ds_span[udata->depth] = udata->ds_span[udata->depth - 1]->down->head;
udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
if(udata->ds_span[udata->depth]->down) {
do {
HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high);
if(udata->nelem < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, 0, udata->op_gen)
* (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
if(udata->nelem >= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts) {
if(udata->share_selection) {
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->op_info[0].u.nelmts) - 1,
udata->ds_span[udata->depth]->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
if(NULL == (copied_span_info = H5S__hyper_copy_span_helper(udata->ds_span[udata->depth]->down, udata->ds_rank - udata->depth, 1, udata->op_gen)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination spans")
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->op_info[0].u.nelmts) - 1,
copied_span_info) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(copied_span_info);
copied_span_info = NULL;
}
udata->ds_low[udata->depth] += udata->nelem / udata->ds_span[udata->depth]->down->op_info[0].u.nelmts;
udata->nelem %= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts;
}
break;
}
if(udata->share_selection) {
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
udata->ds_span[udata->depth]->high,
udata->ds_span[udata->depth]->down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
}
else {
if(NULL == (copied_span_info = H5S__hyper_copy_span_helper(udata->ds_span[udata->depth]->down, udata->ds_rank - udata->depth, 1, udata->op_gen)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination spans")
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
udata->ds_span[udata->depth]->high,
copied_span_info) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(copied_span_info);
copied_span_info = NULL;
}
udata->nelem -= udata->ds_span[udata->depth]->down->op_info[0].u.nelmts
* (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1);
udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
HDassert(udata->ds_span[udata->depth]);
udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
} while(udata->nelem > 0);
}
else {
HDassert(udata->ds_rank - udata->depth == 1);
do {
HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high);
if(udata->nelem < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1,
udata->ds_low[udata->depth], udata->ds_low[udata->depth] + udata->nelem - 1, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
udata->ds_low[udata->depth] += udata->nelem;
udata->nelem = 0;
break;
}
if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1,
udata->ds_low[udata->depth], udata->ds_span[udata->depth]->high, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
udata->nelem -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1;
udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
HDassert(udata->ds_span[udata->depth]);
udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
} while(udata->nelem > 0);
}
}
HDassert(udata->skip == 0);
HDassert(udata->nelem == 0);
udata->ps_clean_bitmap = 0;
done:
if(copied_span_info) {
HDassert(ret_value < 0);
H5S__hyper_free_span_info(copied_span_info);
copied_span_info = NULL;
}
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5S__hyper_proj_int_iterate(const H5S_hyper_span_info_t *ss_span_info,
const H5S_hyper_span_info_t *sis_span_info, hsize_t count, unsigned depth,
H5S_hyper_project_intersect_ud_t *udata)
{
const H5S_hyper_span_t *ss_span;
const H5S_hyper_span_t *sis_span;
hsize_t ss_low;
hsize_t sis_low;
hsize_t high;
hsize_t low;
hsize_t old_skip;
hsize_t old_nelem;
hbool_t check_intersect;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
check_intersect = TRUE;
for(u = 0; u < (udata->ss_rank - depth); u++)
if(!H5S_RANGE_OVERLAP(ss_span_info->low_bounds[u],
ss_span_info->high_bounds[u],
sis_span_info->low_bounds[u],
sis_span_info->high_bounds[u])) {
check_intersect = FALSE;
break;
}
if(check_intersect) {
udata->ps_clean_bitmap |= (((uint32_t)1) << depth);
old_skip = udata->skip;
old_nelem = udata->nelem;
for(u = 0; u < count; u++) {
ss_span = ss_span_info->head;
sis_span = sis_span_info->head;
HDassert(ss_span && sis_span);
ss_low = ss_span->low;
sis_low = sis_span->low;
do {
if(H5S_RANGE_OVERLAP(ss_low, ss_span->high,
sis_low, sis_span->high)) {
high = MIN(ss_span->high, sis_span->high);
if(ss_span->down) {
if(ss_low < sis_low) {
low = sis_low;
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, 0, udata->op_gen) * (sis_low - ss_low), FAIL);
}
else
low = ss_low;
if(H5S__hyper_proj_int_iterate(ss_span->down, sis_span->down, high - low + 1, depth + 1, udata) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't iterate over source selections")
}
else {
HDassert(depth == udata->ss_rank - 1);
if(ss_low < sis_low) {
low = sis_low;
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, sis_low - ss_low, FAIL);
}
else
low = ss_low;
udata->nelem += high - low + 1;
}
if(ss_span->high == sis_span->high) {
ss_span = ss_span->next;
if(ss_span)
ss_low = ss_span->low;
sis_span = sis_span->next;
if(sis_span)
sis_low = sis_span->low;
}
else if(ss_span->high == high) {
HDassert(ss_span->high < sis_span->high);
sis_low = high + 1;
ss_span = ss_span->next;
if(ss_span)
ss_low = ss_span->low;
}
else {
HDassert(ss_span->high > sis_span->high);
ss_low = high + 1;
sis_span = sis_span->next;
if(sis_span)
sis_low = sis_span->low;
}
}
else {
if(ss_span->high < sis_low) {
if(ss_span->down)
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, 0, udata->op_gen) * (ss_span->high - ss_low + 1), FAIL);
else
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_low + 1, FAIL);
ss_span = ss_span->next;
if(ss_span)
ss_low = ss_span->low;
}
else {
HDassert(ss_low > sis_span->high);
sis_span = sis_span->next;
if(sis_span)
sis_low = sis_span->low;
}
}
} while(ss_span && sis_span);
if(ss_span && !((depth == 0) && (u == count - 1))) {
if(ss_span->down) {
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, 0, udata->op_gen) * (ss_span->high - ss_low + 1), FAIL);
ss_span = ss_span->next;
while(ss_span) {
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, 0, udata->op_gen) * (ss_span->high - ss_span->low + 1), FAIL);
ss_span = ss_span->next;
}
}
else {
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_low + 1, FAIL);
ss_span = ss_span->next;
while(ss_span) {
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_span->low + 1, FAIL);
ss_span = ss_span->next;
}
}
}
if(udata->ps_clean_bitmap & (((uint32_t)1) << depth)) {
HDassert(u == 0);
if(udata->skip == old_skip) {
HDassert(udata->nelem >= old_nelem);
udata->nelem += (count - 1) * (udata->nelem - old_nelem);
}
else if(udata->nelem == 0) {
HDassert(old_nelem == 0);
HDassert(udata->skip > old_skip);
udata->skip += (count - 1) * (udata->skip - old_skip);
}
else {
hsize_t skip_add;
hsize_t nelem_add;
HDassert(udata->nelem > 0);
HDassert(udata->skip > old_skip);
HDassert(old_nelem == 0);
skip_add = udata->skip - old_skip;
nelem_add = udata->nelem - old_nelem;
for(u = 1; u < count; u++) {
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, skip_add, FAIL);
udata->nelem += nelem_add;
}
}
break;
}
}
}
else if(depth > 0)
H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper((H5S_hyper_span_info_t *)ss_span_info, 0, udata->op_gen) * count, FAIL);
if(depth == 0) {
if(udata->nelem > 0)
if(H5S__hyper_proj_int_build_proj(udata) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't add elements to projected selection")
for(u = udata->ds_rank - 1; u > 0; u--)
if(udata->ps_span_info[u]) {
if(H5S__hyper_append_span(&udata->ps_span_info[u - 1],
udata->ds_rank - u + 1, udata->ds_low[u - 1],
udata->ds_low[u - 1],
udata->ps_span_info[u]) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
H5S__hyper_free_span_info(udata->ps_span_info[u]);
udata->ps_span_info[u] = NULL;
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space,
const H5S_t *src_intersect_space, H5S_t *proj_space,
hbool_t share_selection)
{
H5S_hyper_project_intersect_ud_t udata;
const H5S_hyper_span_info_t *ss_span_info;
const H5S_hyper_span_info_t *ds_span_info;
H5S_hyper_span_info_t *ss_span_info_buf = NULL;
H5S_hyper_span_info_t *ds_span_info_buf = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(src_space);
HDassert(dst_space);
HDassert(src_intersect_space);
HDassert(proj_space);
HDassert(H5S_GET_EXTENT_NDIMS(src_space) == H5S_GET_EXTENT_NDIMS(src_intersect_space));
HDassert(H5S_GET_SELECT_NPOINTS(src_space) == H5S_GET_SELECT_NPOINTS(dst_space));
HDassert(H5S_GET_SELECT_TYPE(src_space) != H5S_SEL_POINTS);
HDassert(H5S_GET_SELECT_TYPE(dst_space) != H5S_SEL_POINTS);
HDassert(H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_HYPERSLABS);
if(H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_HYPERSLABS) {
if(NULL == src_space->select.sel_info.hslab->span_lst)
if(H5S__hyper_generate_spans((H5S_t *)src_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source hyperslab selection")
ss_span_info = src_space->select.sel_info.hslab->span_lst;
}
else {
HDassert(H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_ALL);
if(NULL == (ss_span_info_buf = H5S__hyper_make_spans(H5S_GET_EXTENT_NDIMS(src_space),
H5S_hyper_zeros_g, H5S_hyper_zeros_g, H5S_hyper_ones_g, src_space->extent.size)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't create span tree for ALL source space")
ss_span_info = ss_span_info_buf;
}
if(H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_HYPERSLABS) {
if(NULL == dst_space->select.sel_info.hslab->span_lst)
if(H5S__hyper_generate_spans((H5S_t *)dst_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for dsetination hyperslab selection")
ds_span_info = dst_space->select.sel_info.hslab->span_lst;
}
else {
HDassert(H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_ALL);
if(NULL == (ds_span_info_buf = H5S__hyper_make_spans(H5S_GET_EXTENT_NDIMS(dst_space),
H5S_hyper_zeros_g, H5S_hyper_zeros_g, H5S_hyper_ones_g, dst_space->extent.size)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't create span tree for ALL destination space")
ds_span_info = ds_span_info_buf;
}
if(NULL == src_intersect_space->select.sel_info.hslab->span_lst)
if(H5S__hyper_generate_spans((H5S_t *)src_intersect_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source intersect hyperslab selection")
HDmemset(&udata, 0, sizeof(udata));
udata.ds_span[0] = ds_span_info->head;
udata.ds_low[0] = udata.ds_span[0]->low;
udata.ss_rank = H5S_GET_EXTENT_NDIMS(src_space);
udata.ds_rank = H5S_GET_EXTENT_NDIMS(dst_space);
udata.op_gen = H5S__hyper_get_op_gen();
udata.share_selection = share_selection;
if(H5S__hyper_proj_int_iterate(ss_span_info, src_intersect_space->select.sel_info.hslab->span_lst, 1, 0, &udata) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "selection iteration failed")
if(H5S_SELECT_RELEASE(proj_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
if(udata.ps_span_info[0]) {
if(NULL == (proj_space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info")
proj_space->select.type = H5S_sel_hyper;
proj_space->select.sel_info.hslab->unlim_dim = -1;
proj_space->select.sel_info.hslab->span_lst = udata.ps_span_info[0];
udata.ps_span_info[0] = NULL;
proj_space->select.num_elem = H5S__hyper_spans_nelem(proj_space->select.sel_info.hslab->span_lst);
H5S__hyper_rebuild(proj_space);
}
else
if(H5S_select_none(proj_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection")
done:
if(ss_span_info_buf) {
H5S__hyper_free_span_info(ss_span_info_buf);
ss_span_info_buf = NULL;
}
if(ds_span_info_buf) {
H5S__hyper_free_span_info(ds_span_info_buf);
ds_span_info_buf = NULL;
}
if(ret_value < 0) {
unsigned u;
for(u = 0; u < udata.ds_rank; u++)
if(udata.ps_span_info[u]) {
H5S__hyper_free_span_info(udata.ps_span_info[u]);
udata.ps_span_info[u] = NULL;
}
}
#ifndef NDEBUG
{
unsigned u;
for(u = 0; u < H5S_MAX_RANK; u++)
HDassert(!udata.ps_span_info[u]);
}
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
static void
H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count,
hsize_t *block, hsize_t clip_size)
{
FUNC_ENTER_STATIC_NOERR
if(start >= clip_size) {
if(*block == H5S_UNLIMITED)
*block = 0;
else
*count = 0;
}
else if((*block == H5S_UNLIMITED) || (*block == stride)) {
*block = clip_size - start;
*count = (hsize_t)1;
}
else {
HDassert(*count == H5S_UNLIMITED);
*count = (clip_size - start + stride - (hsize_t)1) / stride;
HDassert(*count > (hsize_t)0);
}
FUNC_LEAVE_NOAPI_VOID
}
herr_t
H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size)
{
H5S_hyper_sel_t *hslab = NULL;
hsize_t orig_count;
int orig_unlim_dim;
H5S_hyper_dim_t *diminfo = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space);
hslab = space->select.sel_info.hslab;
HDassert(hslab);
HDassert(hslab->unlim_dim >= 0);
HDassert(!hslab->span_lst);
orig_unlim_dim = hslab->unlim_dim;
diminfo = &hslab->diminfo.opt[orig_unlim_dim];
orig_count = diminfo->count;
H5S__hyper_get_clip_diminfo(diminfo->start, diminfo->stride, &diminfo->count, &diminfo->block, clip_size);
space->select.sel_info.hslab->unlim_dim = -1;
if((diminfo->block == 0) || (diminfo->count == 0)) {
if(H5S_select_none(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection")
hslab = NULL;
diminfo = NULL;
}
else if(orig_count == (hsize_t)1) {
space->select.num_elem = diminfo->block * hslab->num_elem_non_unlim;
hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
}
else {
space->select.num_elem = diminfo->count * diminfo->block * hslab->num_elem_non_unlim;
HDassert(clip_size > diminfo->start);
if(((diminfo->stride * (diminfo->count - (hsize_t)1)) + diminfo->block)
> (clip_size - diminfo->start)) {
hsize_t start[H5S_MAX_RANK];
hsize_t block[H5S_MAX_RANK];
unsigned u;
HDmemset(start, 0, sizeof(start));
for(u = 0; u < space->extent.rank; u++)
if((int)u == orig_unlim_dim)
block[u] = clip_size;
else
block[u] = H5S_MAX_SIZE;
if(!hslab->span_lst)
if(H5S__hyper_generate_spans(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to generate span tree")
hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
if(H5S__generate_hyperslab(space, H5S_SELECT_AND, start, H5S_hyper_ones_g, H5S_hyper_ones_g, block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs")
}
else
hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
}
if(hslab && (H5S_DIMINFO_VALID_YES == hslab->diminfo_valid))
hslab->diminfo.high_bounds[orig_unlim_dim] =
hslab->diminfo.opt[orig_unlim_dim].start +
hslab->diminfo.opt[orig_unlim_dim].stride * (hslab->diminfo.opt[orig_unlim_dim].count - 1) +
(hslab->diminfo.opt[orig_unlim_dim].block - 1);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static hsize_t
H5S__hyper_get_clip_extent_real(const H5S_t *clip_space, hsize_t num_slices,
hbool_t incl_trail)
{
const H5S_hyper_dim_t *diminfo;
hsize_t count;
hsize_t rem_slices;
hsize_t ret_value = 0;
FUNC_ENTER_STATIC_NOERR
HDassert(clip_space);
HDassert(clip_space->select.sel_info.hslab);
HDassert(clip_space->select.sel_info.hslab->unlim_dim >= 0);
diminfo = &clip_space->select.sel_info.hslab->diminfo.opt[clip_space->select.sel_info.hslab->unlim_dim];
if(num_slices == 0)
ret_value = incl_trail ? diminfo->start : 0;
else if((diminfo->block == H5S_UNLIMITED)
|| (diminfo->block == diminfo->stride))
ret_value = diminfo->start + num_slices;
else {
HDassert(diminfo->count == H5S_UNLIMITED);
count = num_slices / diminfo->block;
rem_slices = num_slices - (count * diminfo->block);
if(rem_slices > 0)
ret_value = diminfo->start + (count * diminfo->stride) + rem_slices;
else {
if(incl_trail)
ret_value = diminfo->start + (count * diminfo->stride);
else
ret_value = diminfo->start + ((count - (hsize_t)1)
* diminfo->stride) + diminfo->block;
}
}
FUNC_LEAVE_NOAPI(ret_value)
}
hsize_t
H5S_hyper_get_clip_extent(const H5S_t *clip_space, const H5S_t *match_space,
hbool_t incl_trail)
{
hsize_t num_slices;
hsize_t ret_value = 0;
FUNC_ENTER_NOAPI(0)
HDassert(clip_space);
HDassert(match_space);
HDassert(clip_space->select.sel_info.hslab->unlim_dim >= 0);
if(match_space->select.type->type == H5S_SEL_NONE)
num_slices = (hsize_t)0;
else {
HDassert(match_space->select.type->type == H5S_SEL_HYPERSLABS);
HDassert(match_space->select.sel_info.hslab);
num_slices = match_space->select.num_elem
/ clip_space->select.sel_info.hslab->num_elem_non_unlim;
HDassert((match_space->select.num_elem
% clip_space->select.sel_info.hslab->num_elem_non_unlim) == 0);
}
ret_value = H5S__hyper_get_clip_extent_real(clip_space, num_slices, incl_trail);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
hsize_t
H5S_hyper_get_clip_extent_match(const H5S_t *clip_space,
const H5S_t *match_space, hsize_t match_clip_size, hbool_t incl_trail)
{
const H5S_hyper_dim_t *match_diminfo;
hsize_t count;
hsize_t block;
hsize_t num_slices;
hsize_t ret_value = 0;
FUNC_ENTER_NOAPI(0)
HDassert(clip_space);
HDassert(match_space);
HDassert(clip_space->select.sel_info.hslab);
HDassert(match_space->select.sel_info.hslab);
HDassert(clip_space->select.sel_info.hslab->unlim_dim >= 0);
HDassert(match_space->select.sel_info.hslab->unlim_dim >= 0);
HDassert(clip_space->select.sel_info.hslab->num_elem_non_unlim
== match_space->select.sel_info.hslab->num_elem_non_unlim);
match_diminfo = &match_space->select.sel_info.hslab->diminfo.opt[match_space->select.sel_info.hslab->unlim_dim];
count = match_diminfo->count;
block = match_diminfo->block;
H5S__hyper_get_clip_diminfo(match_diminfo->start, match_diminfo->stride, &count, &block, match_clip_size);
if((block == 0) || (count == 0))
num_slices = (hsize_t)0;
else if(count == (hsize_t)1)
num_slices = block;
else {
num_slices = block * count;
HDassert(match_clip_size >= match_diminfo->start);
if(((match_diminfo->stride * (count - (hsize_t)1)) + block)
> (match_clip_size - match_diminfo->start)) {
HDassert((((match_diminfo->stride * (count - (hsize_t)1)) + block)
- (match_clip_size - match_diminfo->start)) < num_slices);
num_slices -= ((match_diminfo->stride * (count - (hsize_t)1))
+ block) - (match_clip_size - match_diminfo->start);
}
}
ret_value = H5S__hyper_get_clip_extent_real(clip_space, num_slices, incl_trail);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5S_t *
H5S_hyper_get_unlim_block(const H5S_t *space, hsize_t block_index)
{
H5S_hyper_sel_t *hslab;
H5S_t *space_out = NULL;
hsize_t start[H5S_MAX_RANK];
hsize_t stride[H5S_MAX_RANK];
hsize_t count[H5S_MAX_RANK];
hsize_t block[H5S_MAX_RANK];
unsigned u;
H5S_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(space);
hslab = space->select.sel_info.hslab;
HDassert(hslab);
HDassert(hslab->unlim_dim >= 0);
HDassert(hslab->diminfo.opt[hslab->unlim_dim].count == H5S_UNLIMITED);
for(u = 0; u < space->extent.rank; u++) {
if((int)u == hslab->unlim_dim){
start[u] = hslab->diminfo.opt[u].start + (block_index
* hslab->diminfo.opt[u].stride);
count[u] = (hsize_t)1;
}
else {
start[u] = hslab->diminfo.opt[u].start;
count[u] = hslab->diminfo.opt[u].count;
}
stride[u] = hslab->diminfo.opt[u].stride;
block[u] = hslab->diminfo.opt[u].block;
}
if(NULL == (space_out = H5S_create(H5S_SIMPLE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "unable to create output dataspace")
if(H5S__extent_copy_real(&space_out->extent, &space->extent, TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "unable to copy destination space extent")
if(H5S_select_hyperslab(space_out, H5S_SELECT_SET, start, stride, count, block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "can't select hyperslab")
ret_value = space_out;
done:
if(!ret_value)
if(space_out && H5S_close(space_out) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, NULL, "unable to release dataspace")
FUNC_LEAVE_NOAPI(ret_value)
}
hsize_t
H5S_hyper_get_first_inc_block(const H5S_t *space, hsize_t clip_size,
hbool_t *partial)
{
H5S_hyper_sel_t *hslab;
H5S_hyper_dim_t *diminfo;
hsize_t ret_value = 0;
FUNC_ENTER_NOAPI(0)
HDassert(space);
hslab = space->select.sel_info.hslab;
HDassert(hslab);
HDassert(hslab->unlim_dim >= 0);
HDassert(hslab->diminfo.opt[hslab->unlim_dim].count == H5S_UNLIMITED);
diminfo = &hslab->diminfo.opt[hslab->unlim_dim];
if(diminfo->start >= clip_size) {
ret_value = 0;
if(partial)
partial = FALSE;
}
else {
ret_value = (clip_size - diminfo->start + diminfo->stride
- diminfo->block) / diminfo->stride;
if(partial) {
if((diminfo->stride * ret_value) < (clip_size - diminfo->start))
*partial = TRUE;
else
*partial = FALSE;
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5Sis_regular_hyperslab(hid_t spaceid)
{
H5S_t *space;
htri_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE1("t", "i", spaceid);
if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
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")
ret_value = H5S__hyper_is_regular(space);
done:
FUNC_LEAVE_API(ret_value)
}
herr_t
H5Sget_regular_hyperslab(hid_t spaceid, hsize_t start[], hsize_t stride[],
hsize_t count[], hsize_t block[])
{
H5S_t *space;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE5("e", "i*h*h*h*h", spaceid, start, stride, count, block);
if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
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")
if(TRUE != H5S__hyper_is_regular(space))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a regular hyperslab selection")
if(start)
for(u = 0; u < space->extent.rank; u++)
start[u] = space->select.sel_info.hslab->diminfo.app[u].start;
if(stride)
for(u = 0; u < space->extent.rank; u++)
stride[u] = space->select.sel_info.hslab->diminfo.app[u].stride;
if(count)
for(u = 0; u < space->extent.rank; u++)
count[u] = space->select.sel_info.hslab->diminfo.app[u].count;
if(block)
for(u = 0; u < space->extent.rank; u++)
block[u] = space->select.sel_info.hslab->diminfo.app[u].block;
done:
FUNC_LEAVE_API(ret_value)
}