summaryrefslogtreecommitdiffstats
path: root/src/H5Shyper.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2002-04-09 12:47:34 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2002-04-09 12:47:34 (GMT)
commit1ffe083f61eacb68e0a91e46d6a6377813849d5a (patch)
treea6fb3175bd830445fdd56b285012032b187aa681 /src/H5Shyper.c
parente403006cc276b29a4b5f3f8fc6c7b11796d1b8d0 (diff)
downloadhdf5-1ffe083f61eacb68e0a91e46d6a6377813849d5a.zip
hdf5-1ffe083f61eacb68e0a91e46d6a6377813849d5a.tar.gz
hdf5-1ffe083f61eacb68e0a91e46d6a6377813849d5a.tar.bz2
[svn-r5152] Purpose:
New Feature Description: Added new H5Dfill() routine to fill the elements in a selection for a memory buffer with a fill value. This is a user API wrapper around some internal routines which were needed for the fill-value modifications from Raymond as well as Pedro's code for reducing the size of a chunked dataset. Platforms tested: FreeBSD 4.5 (sleipnir) [and IRIX64 6.5 (modi4) in parallel, in a few minutes]
Diffstat (limited to 'src/H5Shyper.c')
-rw-r--r--src/H5Shyper.c411
1 files changed, 403 insertions, 8 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 4c1f3f5..029b7d7 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -6047,18 +6047,17 @@ H5S_hyper_select_regular(const H5S_t *space)
else
ret_value=FALSE;
-done:
FUNC_LEAVE (ret_value);
} /* H5S_hyper_select_regular() */
/*--------------------------------------------------------------------------
NAME
- H5S_hyper_select_iterate_helper
+ H5S_hyper_select_iterate_mem_gen
PURPOSE
Internal routine to iterate over the elements of a span tree hyperslab selection
USAGE
- herr_t H5S_iterate_hyperslab_io(iter_info)
+ herr_t H5S_hyper_select_iterate_mem_gen(iter_info)
H5S_hyper_iter_info_t *iter_info; IN/OUT: Block of iteration parameters to pass into recursive calls
RETURNS
Non-negative on success, negative on failure
@@ -6071,7 +6070,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_hyper_select_iterate_helper(H5S_hyper_iter_info_t *iter_info)
+H5S_hyper_select_iterate_mem_gen(H5S_hyper_iter_info_t *iter_info)
{
const H5S_t *space; /* Dataspace operating with */
H5S_sel_iter_t *iter; /* Selection iterator */
@@ -6090,7 +6089,7 @@ H5S_hyper_select_iterate_helper(H5S_hyper_iter_info_t *iter_info)
unsigned u; /* Index variable */
herr_t ret_value=FAIL;
- FUNC_ENTER (H5S_hyper_select_iterate_helper, FAIL);
+ FUNC_ENTER (H5S_hyper_select_iterate_mem_gen, FAIL);
/* Check args */
assert(iter_info);
@@ -6244,7 +6243,7 @@ H5S_hyper_select_iterate_helper(H5S_hyper_iter_info_t *iter_info)
done:
#endif /* LATER */
FUNC_LEAVE (ret_value);
-} /* end H5S_hyper_select_iterate_helper() */
+} /* end H5S_hyper_select_iterate_mem_gen() */
/*--------------------------------------------------------------------------
@@ -6503,7 +6502,7 @@ H5S_hyper_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t
iter_info.op_data=operator_data;
/* Call the recursive iterator routine */
- ret_value=H5S_hyper_select_iterate_helper(&iter_info);
+ ret_value=H5S_hyper_select_iterate_mem_gen(&iter_info);
} /* end else */
/* Release selection iterator */
@@ -6571,6 +6570,402 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5S_hyper_select_fill_gen
+ PURPOSE
+ Fill a hyperslab selection in memory with a value
+ USAGE
+ herr_t H5S_hyper_select_fill_gen(fill,fill_size,space,buf)
+ const void *fill; IN: Pointer to fill value to use
+ size_t fill_size; IN: Size of elements in memory buffer & size of
+ fill value
+ H5S_t *space; IN: Dataspace describing memory buffer &
+ containing selection to use.
+ void *buf; IN/OUT: Memory buffer to fill selection in
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Use the selection in the dataspace to fill elements in a memory buffer.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The memory buffer elements are assumed to have the same datatype as the
+ fill value being placed into them.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S_hyper_select_fill_gen(const void *fill, size_t fill_size, H5S_t *space, void *buf)
+{
+ H5S_hyper_span_info_t *spans=NULL; /* Pointer to copy of the span tree */
+ H5S_hyper_span_info_t *tmp_spans; /* Temporary pointer to a span tree */
+ H5S_hyper_span_t *span[H5O_LAYOUT_NDIMS]; /* Array of pointers to span nodes */
+ H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
+ hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */
+ hssize_t abs_arr[H5O_LAYOUT_NDIMS]; /* Absolute hyperslab span position */
+ hssize_t *off_arr; /* Offset within the dataspace extent */
+ hsize_t acc; /* Accumulator for computing cumulative sizes */
+ int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ int curr_dim; /* Current dimension being operated on */
+ int ndims; /* Number of dimensions of dataset */
+ hsize_t span_io; /* Number of elements in current span to actually process */
+ hsize_t num_elem; /* Number of elements in the selection */
+ uint8_t *loc; /* Current element location pointer */
+ int i; /* Index variable */
+ unsigned u; /* Index variable */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER (H5S_hyper_select_fill_gen, FAIL);
+
+ /* Set the rank of the fastest changing dimension */
+ ndims=space->extent.u.simple.rank;
+ fast_dim=(ndims-1);
+
+ /* Set the pointer to the selection offset in the dataspace */
+ off_arr=space->select.offset;
+
+ /* Make a copy of the span tree to iterate over */
+ spans=H5S_hyper_copy_span(space->select.sel_info.hslab.span_lst);
+
+ /* Set the nelem & pstride values according to the element size */
+ H5S_hyper_span_precompute(spans,fill_size);
+
+ /* Build arrays of span heads & offsets in each dimension */
+ for(u=0, tmp_spans=spans; u<space->extent.u.simple.rank; u++) {
+ /* Set the pointers to the initial span in each dimension */
+ assert(tmp_spans);
+ assert(tmp_spans->head);
+
+ /* Set the pointer to the first span in the list for this node */
+ span[u] = tmp_spans->head;
+
+ /* Set the initial offset to low bound of span */
+ abs_arr[u]=span[u]->low;
+
+ /* Get the pointer to the next level down */
+ tmp_spans=tmp_spans->head->down;
+ } /* end for */
+
+ /* Compute sizes of "slab" in each dimension */
+ for(i=fast_dim, acc=fill_size; i>=0; i--) {
+ slab[i]=acc;
+ acc*=space->extent.u.simple.size[i];
+ } /* end for */
+
+ /* Set the offset of the first element iterated on */
+ for(i=0, loc=buf; i<ndims; i++)
+ /* Compute the sequential element offset */
+ loc+=(abs_arr[i]+off_arr[i])*slab[i];
+
+ /* Get the number of elements in selection */
+ num_elem=space->select.num_elem;
+
+ /* Get the pointer to the current span nodes */
+ curr_span=span[fast_dim];
+
+ /* Go iterate over the hyperslabs */
+ while(num_elem>0) {
+ /* Loop through the fastest dim's spans */
+ while(curr_span!=NULL) {
+ /* Compute the number of elements to attempt in this span */
+ span_io=(curr_span->high-curr_span->low)+1;
+
+ /* Double check that things haven't gotten out of sync */
+ assert(num_elem>0);
+
+ /* Fill the elements in the current block */
+ H5_CHECK_OVERFLOW(span_io,hsize_t,size_t);
+ H5V_array_fill(loc, fill, fill_size, (size_t)span_io);
+
+ /* Increment the buffer offset */
+ loc+=curr_span->pstride;
+
+ /* Decrement the number of elements left */
+ num_elem-=span_io;
+
+ /* Advance span in fastest dimension */
+ curr_span=curr_span->next;
+ } /* end while */
+
+ /* Check if there are more elements left */
+ if(num_elem>0) {
+ /* Recursively advance to next offset (not necessarily span) in next dimension up */
+
+ /* Start at the fastest dim */
+ curr_dim=fast_dim-1;
+
+ /* Get the pointer to the correct dimension */
+ curr_span=span[curr_dim];
+
+ /* Work back up through the dimensions */
+ while(curr_dim>=0) {
+ /* Increment position in span */
+ abs_arr[curr_dim]++;
+
+ /* Check if we are still within the span */
+ if(abs_arr[curr_dim]<=curr_span->high) {
+ break;
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span=curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(curr_span!=NULL) {
+ /* Reset the offset for the dim */
+ abs_arr[curr_dim]=curr_span->low;
+
+ break;
+ } /* end if */
+ else {
+ /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
+ curr_dim--;
+
+ /* Reset the curr_span to the next dim */
+ if(curr_dim>=0)
+ curr_span=span[curr_dim];
+ } /* end else */
+ } /* end else */
+ } /* end while */
+
+ /* Reset the span in the current dimension */
+ span[curr_dim]=curr_span;
+
+ /* Walk back down the iterator positions, reseting them */
+ while(curr_dim<fast_dim) {
+ assert(curr_span);
+ assert(curr_span->down);
+ assert(curr_span->down->head);
+
+ /* Set the new span for this dimension */
+ span[curr_dim+1]=curr_span->down->head;
+
+ /* Advance span down the tree */
+ curr_span=curr_span->down->head;
+
+ /* Reset the offset for the dim */
+ abs_arr[curr_dim+1]=curr_span->low;
+
+ /* Increment current dimension */
+ curr_dim++;
+ } /* end while */
+
+ /* Verify that the curr_span points to the fastest dim */
+ assert(curr_span==span[fast_dim]);
+
+ /* Verify that the offset is correct for the fastest dim */
+ assert(abs_arr[fast_dim]==curr_span->low);
+
+ /* Recompute offset in buffer */
+ for(i=0, loc=buf; i<ndims; i++)
+ loc+=(abs_arr[i]+off_arr[i])*slab[i];
+ } /* end if */
+ } /* end while */
+
+#ifdef LATER
+done:
+#endif /* LATER */
+ /* Free the copy of the selections span tree */
+ if(spans!=NULL)
+ H5S_hyper_free_span_info(spans);
+
+ FUNC_LEAVE (ret_value);
+} /* end H5S_hyper_select_fill_gen() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_select_fill_opt
+ PURPOSE
+ Fill a hyperslab selection in memory with a value
+ USAGE
+ herr_t H5S_hyper_select_fill_opt(fill,fill_size,space,buf)
+ const void *fill; IN: Pointer to fill value to use
+ size_t fill_size; IN: Size of elements in memory buffer & size of
+ fill value
+ H5S_t *space; IN: Dataspace describing memory buffer &
+ containing selection to use.
+ void *buf; IN/OUT: Memory buffer to fill selection in
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Use the selection in the dataspace to fill elements in a memory buffer.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The memory buffer elements are assumed to have the same datatype as the
+ fill value being placed into them.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S_hyper_select_fill_opt(const void *fill, size_t fill_size, H5S_t *space, void *buf)
+{
+ H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
+ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */
+ hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab blocks */
+ hsize_t slab[H5O_LAYOUT_NDIMS]; /* Size of objects in buffer */
+ hsize_t acc; /* Size accumulator */
+ hsize_t num_elem; /* Number of elements in the selection */
+ hsize_t fast_elem; /* Block size in the fastest dimension */
+ hsize_t fast_stride; /* Stride in the fastest dimension */
+ hssize_t temp_off; /* Offset in a given dimension */
+ uint8_t *loc; /* Current element location */
+ int i; /* Counter */
+ unsigned u; /* Counter */
+ int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ int temp_dim; /* Temporary rank holder */
+ unsigned ndims; /* Rank of the dataspace */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER (H5S_hyper_select_fill_opt, FAIL);
+
+ /* Set some convienence values */
+ ndims=space->extent.u.simple.rank;
+ fast_dim=ndims-1;
+ diminfo=space->select.sel_info.hslab.diminfo;
+
+ /* Build the table of next-dimension down 'element' sizes */
+ for(i=fast_dim, acc=fill_size; i>=0; i--) {
+ slab[i]=acc;
+ acc*=space->extent.u.simple.size[i];
+ } /* end for */
+
+ /* Build the tables of count & block sizes as well as the initial starting location */
+ for(u=0, loc=buf; u<ndims; u++) {
+ tmp_count[u]=diminfo[u].count;
+ tmp_block[u]=diminfo[u].block;
+ loc+=(diminfo[u].start+space->select.offset[u])*slab[u];
+ } /* end for */
+
+ /* Get the number of elements in selection */
+ num_elem=space->select.num_elem;
+
+ /* Get the number of elements in the fastest dimension of the selection */
+ fast_elem=tmp_block[fast_dim];
+ fast_stride=diminfo[fast_dim].stride;
+
+ /* Go iterate over the hyperslabs */
+ while(num_elem>0) {
+ /* Iterate over the blocks in the fastest dimension */
+ while(tmp_count[fast_dim]>0) {
+ /* Double check that things haven't gotten out of sync */
+ assert(num_elem>0);
+
+ /* Fill the elements in the current block */
+ H5_CHECK_OVERFLOW(fast_elem,hsize_t,size_t);
+ H5V_array_fill(loc, fill, fill_size, (size_t)fast_elem);
+
+ /* Advance the pointer in the memory buffer */
+ loc+=(fast_stride*fill_size);
+
+ /* Decrement the block count */
+ tmp_count[fast_dim]--;
+
+ /* Decrement the number of elements to process */
+ num_elem-=fast_elem;
+ } /* end while */
+
+ /* Work on other dimensions if necessary */
+ if(num_elem>0) {
+ /* Reset the sequence and block counts */
+ tmp_count[fast_dim]=diminfo[fast_dim].count;
+
+ /* Bubble up the decrement to the slower changing dimensions */
+ temp_dim=fast_dim-1;
+ while(temp_dim>=0) {
+ /* Decrement the sequence count in this dimension */
+ tmp_block[temp_dim]--;
+
+ /* Check if we are still in the sequence */
+ if(tmp_block[temp_dim]>0)
+ break;
+
+ /* Reset the sequence count in this dimension */
+ tmp_block[temp_dim]=diminfo[temp_dim].block;
+
+ /* Decrement the block count */
+ tmp_count[temp_dim]--;
+
+ /* Check if we have more blocks left */
+ if(tmp_count[temp_dim]>0)
+ break;
+
+ /* Reset the block count in this dimension */
+ tmp_count[temp_dim]=diminfo[temp_dim].count;
+
+ /* Wrapped a dimension, go up to next dimension */
+ temp_dim--;
+ } /* end while */
+
+ /* Re-compute buffer location */
+ for(loc=buf,u=0; u<ndims; u++) {
+ temp_off=(diminfo[u].start+space->select.offset[u])
+ +diminfo[u].stride*(diminfo[u].count-tmp_count[u])
+ +(diminfo[u].block-tmp_block[u]);
+ loc+=temp_off*slab[u];
+ } /* end for */
+ } /* end if */
+ } /* end while */
+
+#ifdef LATER
+done:
+#endif /* LATER */
+ FUNC_LEAVE (ret_value);
+} /* end H5S_hyper_select_fill_opt() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_select_fill
+ PURPOSE
+ Fill a hyperslab selection in memory with a value
+ USAGE
+ herr_t H5S_hyper_select_fill(fill,fill_size,space,buf)
+ const void *fill; IN: Pointer to fill value to use
+ size_t fill_size; IN: Size of elements in memory buffer & size of
+ fill value
+ H5S_t *space; IN: Dataspace describing memory buffer &
+ containing selection to use.
+ void *buf; IN/OUT: Memory buffer to fill selection in
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Use the selection in the dataspace to fill elements in a memory buffer.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The memory buffer elements are assumed to have the same datatype as the
+ fill value being placed into them.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_hyper_select_fill(const void *fill, size_t fill_size, H5S_t *space, void *buf)
+{
+ herr_t ret_value=SUCCEED; /* return value */
+
+ FUNC_ENTER (H5S_hyper_select_fill, FAIL);
+
+ /* Check args */
+ assert(fill);
+ assert(fill_size>0);
+ assert(space);
+ assert(buf);
+
+ /* Fill the selection in the memory buffer */
+
+ /* Check for the special case of just one H5Sselect_hyperslab call made */
+ if(space->select.sel_info.hslab.diminfo!=NULL)
+ /* Use optimized call to fill regular hyperslab */
+ ret_value=H5S_hyper_select_fill_opt(fill, fill_size, space, buf);
+ else
+ /* Call the general fill routine */
+ ret_value=H5S_hyper_select_fill_gen(fill, fill_size, space, buf);
+
+ FUNC_LEAVE (ret_value);
+} /* H5S_hyper_select_fill() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_hyper_recover_span
PURPOSE
Recover a generated span, if appropriate
@@ -6703,7 +7098,7 @@ H5S_hyper_append_span (H5S_hyper_span_t **prev_span, H5S_hyper_span_info_t ** sp
} /* end if */
} /* end if */
- /* Indicate elements to previous span */
+ /* Indicate elements from previous span */
new_span->pstride=low-(*prev_span)->low;
/* Append to end of merged spans list */