diff options
Diffstat (limited to 'src/H5Shyper.c')
-rw-r--r-- | src/H5Shyper.c | 240 |
1 files changed, 196 insertions, 44 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 8acbfd5..455a251 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -57,6 +57,7 @@ static hssize_t H5S_hyper_serial_size(const H5S_t *space); static herr_t H5S_hyper_serialize(const H5S_t *space, uint8_t *buf); static herr_t H5S_hyper_deserialize(H5S_t *space, const uint8_t *buf); 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 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); @@ -90,6 +91,7 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{ H5S_hyper_serialize, H5S_hyper_deserialize, H5S_hyper_bounds, + H5S_hyper_offset, H5S_hyper_is_contiguous, H5S_hyper_is_single, H5S_hyper_is_regular, @@ -275,12 +277,17 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space) /* Don't flatten adjacent elements into contiguous block if the * element size is 0. This is for the H5S_select_shape_same() code. */ - if(iter->elmt_size>0) { + if(iter->elmt_size > 0) { /* Check for any "contiguous" blocks that can be flattened */ - for(u=rank-1; u>0; u--) { - if(tdiminfo[u].count==1 && tdiminfo[u].block==mem_size[u]) + 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; + } /* end if */ + else + iter->u.hyp.flattened[u] = FALSE; } /* end for */ + iter->u.hyp.flattened[0] = FALSE; } /* end if */ /* Check if the regular selection can be "flattened" */ @@ -430,23 +437,59 @@ H5S_hyper_iter_coords (const H5S_sel_iter_t *iter, hsize_t *coords) /* Check for a single "regular" hyperslab */ if(iter->u.hyp.diminfo_valid) { /* Check if this is a "flattened" regular hyperslab selection */ - if(iter->u.hyp.iter_rank!=0 && iter->u.hyp.iter_rank<iter->rank) { - unsigned flat_dim; /* The rank of the flattened dimension */ + if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) { + int u, v; /* Dimension indices */ + + /* Set the starting rank of both the "natural" & "flattened" dimensions */ + u = iter->rank - 1; + v = iter->u.hyp.iter_rank - 1; + + /* Construct the "natural" dimensions from a set of flattened coordinates */ + while(u >= 0) { + if(iter->u.hyp.flattened[u]) { + int begin = u; /* The rank of the first flattened dimension */ + + /* Walk up through as many flattened dimensions as possible */ + do { + u--; + } while(u >= 0 && iter->u.hyp.flattened[u]); - /* Get the rank of the flattened dimension */ - flat_dim=iter->u.hyp.iter_rank-1; + /* Compensate for possibly overshooting dim 0 */ + if(u < 0) + u = 0; - /* Copy the coordinates up to where things got flattened */ - HDmemcpy(coords,iter->u.hyp.off,sizeof(hsize_t)*flat_dim); + /* Sanity check */ + HDassert(v >= 0); - /* Compute the coordinates for the flattened dimensions */ - H5V_array_calc(iter->u.hyp.off[flat_dim],iter->rank-flat_dim,&(iter->dims[flat_dim]),&(coords[flat_dim])); + /* Compute the coords for the flattened dimensions */ + H5V_array_calc(iter->u.hyp.off[v], (unsigned)((begin - u) + 1), &(iter->dims[u]), &(coords[u])); + + /* Continue to faster dimension in both indices */ + u--; + v--; + } /* end if */ + else { + /* Walk up through as many non-flattened dimensions as possible */ + while(u >= 0 && !iter->u.hyp.flattened[u]) { + /* Sanity check */ + HDassert(v >= 0); + + /* Copy the coordinate */ + coords[u] = iter->u.hyp.off[v]; + + /* Continue to faster dimension in both indices */ + u--; + v--; + } /* end while */ + } /* end else */ + } /* end while */ + HDassert(v < 0); } /* end if */ else - HDmemcpy(coords,iter->u.hyp.off,sizeof(hsize_t)*iter->rank); + HDmemcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank); } /* end if */ else - HDmemcpy(coords,iter->u.hyp.off,sizeof(hsize_t)*iter->rank); + HDmemcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank); FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_hyper_iter_coords() */ @@ -2515,7 +2558,7 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc hid_t dsid; IN: Dataspace ID of selection to query hsize_t startblock; IN: Hyperslab block to start with hsize_t numblocks; IN: Number of hyperslab blocks to get - hsize_t *buf; OUT: List of hyperslab blocks selected + hsize_t buf[]; OUT: List of hyperslab blocks selected RETURNS Non-negative on success, negative on failure DESCRIPTION @@ -2536,13 +2579,14 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, hsize_t numblocks, hsize_t *buf) +H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, + hsize_t numblocks, hsize_t buf[/*numblocks*/]) { H5S_t *space = NULL; /* Dataspace to modify selection of */ herr_t ret_value; /* return value */ FUNC_ENTER_API(H5Sget_select_hyper_blocklist, FAIL); - H5TRACE4("e", "ihh*h", spaceid, startblock, numblocks, buf); + H5TRACE4("e", "ihh*[a2]h", spaceid, startblock, numblocks, buf); /* Check args */ if(buf==NULL) @@ -2708,6 +2752,114 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_hyper_offset + PURPOSE + Gets the linear offset of the first element for the selection. + USAGE + herr_t H5S_hyper_offset(space, offset) + const H5S_t *space; IN: Dataspace pointer of selection to query + hsize_t *offset; OUT: Linear offset of first element in selection + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Retrieves the linear offset (in "units" of elements) of the first element + selected within the dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Calling this function on a "none" selection returns fail. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_offset(const H5S_t *space, hsize_t *offset) +{ + const hssize_t *sel_offset; /* Pointer to the selection's offset */ + const hsize_t *dim_size; /* Pointer to a dataspace's extent */ + hsize_t accum; /* Accumulator for dimension sizes */ + int rank; /* Dataspace rank */ + int i; /* index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_hyper_offset, FAIL) + + HDassert(space); + HDassert(offset); + + /* Start at linear offset 0 */ + *offset = 0; + + /* Set up pointers to arrays of values */ + rank = space->extent.rank; + sel_offset = space->select.offset; + dim_size = space->extent.size; + + /* Check for a "regular" hyperslab selection */ + if(space->select.sel_info.hslab->diminfo_valid) { + const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* Local alias for diminfo */ + + /* Loop through starting coordinates, calculating the linear offset */ + accum = 1; + for(i = (rank - 1); i >= 0; i--) { + hssize_t hyp_offset = (hssize_t)diminfo[i].start + sel_offset[i]; /* Hyperslab's offset in this dimension */ + + /* Check for offset moving selection out of the dataspace */ + if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") + + /* Add the hyperslab's offset in this dimension to the total linear offset */ + *offset += hyp_offset * accum; + + /* Increase the accumulator */ + accum *= dim_size[i]; + } /* end for */ + } /* end if */ + else { + const H5S_hyper_span_t *span; /* Hyperslab span node */ + hsize_t dim_accum[H5S_MAX_RANK]; /* Accumulators, for each dimension */ + + /* Calculate the accumulator for each dimension */ + accum = 1; + for(i = (rank - 1); i >= 0; i--) { + /* Set the accumulator for this dimension */ + dim_accum[i] = accum; + + /* Increase the accumulator */ + accum *= dim_size[i]; + } /* end for */ + + /* Get information for the first span, in the slowest changing dimension */ + span = space->select.sel_info.hslab->span_lst->head; + + /* Work down the spans, computing the linear offset */ + i = 0; + while(span) { + hssize_t hyp_offset = (hssize_t)span->low + sel_offset[i]; /* Hyperslab's offset in this dimension */ + + /* Check for offset moving selection out of the dataspace */ + if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") + + /* Add the hyperslab's offset in this dimension to the total linear offset */ + *offset += hyp_offset * dim_accum[i]; + + /* Advance to first span in "down" dimension */ + if(span->down) { + HDassert(span->down->head); + span = span->down->head; + } /* end if */ + else + span = NULL; + i++; + } /* end while */ + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_hyper_offset() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_hyper_is_contiguous PURPOSE Check if a hyperslab selection is contiguous within the dataspace extent. @@ -2727,12 +2879,10 @@ done: htri_t H5S_hyper_is_contiguous(const H5S_t *space) { - H5S_hyper_span_info_t *spans; /* Hyperslab span info node */ - H5S_hyper_span_t *span; /* Hyperslab span node */ - unsigned u; /* index variable */ unsigned small_contiguous, /* Flag for small contiguous block */ large_contiguous; /* Flag for large contiguous block */ - htri_t ret_value=FALSE; /* return value */ + unsigned u; /* index variable */ + htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOFUNC(H5S_hyper_is_contiguous); @@ -2791,6 +2941,9 @@ H5S_hyper_is_contiguous(const H5S_t *space) ret_value=TRUE; } /* end if */ else { + H5S_hyper_span_info_t *spans; /* Hyperslab span info node */ + H5S_hyper_span_t *span; /* Hyperslab span node */ + /* * For a hyperslab to be contiguous, it must have only one block and * (either it's size must be the same as the dataspace extent's in all @@ -4127,35 +4280,37 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t +htri_t H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset) { unsigned u; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_normalize_offset); + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_normalize_offset) - assert(space); + HDassert(space); - /* Check for 'all' selection, instead of a hyperslab selection */ - /* (Technically, this check shouldn't be in the "hyperslab" routines...) */ - if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_HYPERSLABS) { + /* Check for hyperslab selection & offset changed */ + if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS && space->select.offset_changed) { /* Copy & invert the selection offset */ - for(u=0; u<space->extent.rank; u++) { + for(u = 0; u<space->extent.rank; u++) { old_offset[u] = space->select.offset[u]; space->select.offset[u] = -space->select.offset[u]; } /* end for */ /* Call the existing 'adjust' routine */ - if(H5S_hyper_adjust_s(space, space->select.offset)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization"); + if(H5S_hyper_adjust_s(space, space->select.offset) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization") /* Zero out the selection offset */ HDmemset(space->select.offset, 0, sizeof(hssize_t) * space->extent.rank); + + /* Indicate that the offset was normalized */ + ret_value = TRUE; } /* end if */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_normalize_offset() */ @@ -4183,25 +4338,22 @@ done: herr_t H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_denormalize_offset); + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_denormalize_offset) - assert(space); + HDassert(space); + HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS); - /* Check for 'all' selection, instead of a hyperslab selection */ - /* (Technically, this check shouldn't be in the "hyperslab" routines...) */ - if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_HYPERSLABS) { - /* Call the existing 'adjust' routine */ - if(H5S_hyper_adjust_s(space, old_offset)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization"); + /* Call the existing 'adjust' routine */ + if(H5S_hyper_adjust_s(space, old_offset) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization") - /* Copy the selection offset over */ - HDmemcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank); - } /* end if */ + /* Copy the selection offset over */ + HDmemcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_denormalize_offset() */ |