From 1ffe083f61eacb68e0a91e46d6a6377813849d5a Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 9 Apr 2002 07:47:34 -0500 Subject: [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] --- release_docs/RELEASE.txt | 2 + src/H5D.c | 84 +++++++++ src/H5Dpublic.h | 2 + src/H5F.c | 2 +- src/H5Sall.c | 54 ++++++ src/H5Shyper.c | 411 +++++++++++++++++++++++++++++++++++++++++++- src/H5Spkg.h | 6 + src/H5Spoint.c | 121 ++++++++++--- src/H5Sprivate.h | 2 + src/H5Sselect.c | 69 +++++++- src/H5V.c | 25 ++- test/tselect.c | 432 +++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 1164 insertions(+), 46 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 6c09c6a..1cce91e 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -156,6 +156,8 @@ Documentation New Features ============ + * Added new routine "H5Dfill" to fill a selection with a particular value + in memory. QAK - 2002/04/09 * A new query function H5Tget_member_index has been added for compound and enumeration data types, to retrieve member's index by name. SLU - 2002/04/05 diff --git a/src/H5D.c b/src/H5D.c index 2b0b717..6345862 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -3597,6 +3597,90 @@ done: } /* end H5Dvlen_get_buf_size() */ +/*-------------------------------------------------------------------------- + NAME + H5Dfill + PURPOSE + Fill a selection in memory with a value + USAGE + herr_t H5Dfill(fill, fill_type, space, buf, buf_type) + const void *fill; IN: Pointer to fill value to use + hid_t fill_type_id; IN: Datatype of the fill value + void *buf; IN/OUT: Memory buffer to fill selection within + hid_t buf_type_id; IN: Datatype of the elements in buffer + hid_t space_id; IN: Dataspace describing memory buffer & + containing selection to use. + 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 + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Dfill(const void *fill, hid_t fill_type_id, void *buf, hid_t buf_type_id, hid_t space_id) +{ + H5S_t *space; /* Dataspace */ + H5T_t *fill_type; /* Fill-value datatype */ + H5T_t *buf_type; /* Buffer datatype */ + H5T_path_t *tpath = NULL; /* Conversion information*/ + uint8_t *tconv_buf = NULL; /* Data type conv buffer */ + uint8_t *bkg_buf = NULL; /* Temp conversion buffer */ + size_t src_type_size; /* Size of source type */ + size_t dst_type_size; /* Size of destination type*/ + size_t buf_size; /* Desired buffer size */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER (H5Dfill, FAIL); + + /* Check args */ + if (fill==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid fill value"); + if (buf==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer"); + if (H5I_DATASPACE != H5I_get_type(space_id) || NULL == (space=H5I_object(space_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a dataspace"); + if (H5I_DATATYPE != H5I_get_type(fill_type_id) || NULL == (fill_type=H5I_object(fill_type_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype"); + if (H5I_DATATYPE != H5I_get_type(buf_type_id) || NULL == (buf_type=H5I_object(buf_type_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype"); + + /* Get the memory and file datatype sizes */ + src_type_size = H5T_get_size(fill_type); + dst_type_size = H5T_get_size(buf_type); + + /* Get the maximum buffer size needed and allocate it */ + buf_size=MAX(src_type_size,dst_type_size); + if (NULL==(tconv_buf = H5MM_malloc (buf_size)) || NULL==(bkg_buf = H5MM_calloc(buf_size))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + + /* Copy the user's data into the buffer for conversion */ + HDmemcpy(tconv_buf,fill,src_type_size); + + /* Convert memory buffer into disk buffer */ + /* Set up type conversion function */ + if (NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL))) + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); + + /* Perform data type conversion */ + if (H5T_convert(tpath, fill_type_id, buf_type_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, H5P_DEFAULT)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed"); + + /* Fill the selection in the memory buffer */ + if(H5S_select_fill(tconv_buf, dst_type_size, space, buf)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed"); + +done: + if (tconv_buf) + H5MM_xfree(tconv_buf); + if (bkg_buf) + H5MM_xfree(bkg_buf); + FUNC_LEAVE (ret_value); +} /* H5Dfill() */ + + /*------------------------------------------------------------------------- * Function: H5Ddebug * diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h index b889c35..41e479d 100644 --- a/src/H5Dpublic.h +++ b/src/H5Dpublic.h @@ -57,6 +57,8 @@ __DLL__ herr_t H5Diterate(void *buf, hid_t type_id, hid_t space_id, H5D_operator_t op, void *operator_data); __DLL__ herr_t H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf); __DLL__ herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *size); +__DLL__ herr_t H5Dfill(const void *fill, hid_t fill_type, void *buf, + hid_t buf_type, hid_t space); __DLL__ herr_t H5Ddebug(hid_t dset_id, unsigned int flags); #ifdef __cplusplus diff --git a/src/H5F.c b/src/H5F.c index 71b009a..9c1fd21 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -3280,7 +3280,7 @@ H5F_get_fileno(const H5F_t *f, unsigned long *filenum) /* Retrieve the file's serial number */ if(H5FD_get_fileno(f->shared->lf,filenum)<0) - HRETURN_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno"); + HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno"); done: FUNC_LEAVE(ret_value); diff --git a/src/H5Sall.c b/src/H5Sall.c index ea5eac5..d988de2 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -1057,3 +1057,57 @@ H5S_all_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op FUNC_LEAVE (ret_value); } /* H5S_all_select_iterate() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_all_select_fill + PURPOSE + Fill an "all" selection in memory with a value + USAGE + herr_t H5S_all_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_all_select_fill(const void *fill, size_t fill_size, H5S_t *space, void *buf) +{ + hssize_t nelemts; /* Number of elements in dataspace */ + herr_t ret_value=SUCCEED; /* return value */ + + FUNC_ENTER (H5S_all_select_fill, FAIL); + + /* Check args */ + assert(fill); + assert(fill_size>0); + assert(space); + assert(buf); + + /* Fill the selection in the memory buffer */ + + /* Get the number of elements to iterate through */ + if((nelemts=H5S_get_simple_extent_npoints(space))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements"); + + /* Fill the elements in the buffer */ + H5_CHECK_OVERFLOW(nelemts,hssize_t,size_t); + H5V_array_fill(buf, fill, fill_size, (size_t)nelemts); + +done: + FUNC_LEAVE (ret_value); +} /* H5S_all_select_fill() */ + 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; uextent.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; iselect.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_dimdown); + 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; iextent.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; uselect.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; uselect.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 */ diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 0fc4513..668e9a6 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -138,6 +138,8 @@ __DLL__ herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem, const hssize_t **coord); __DLL__ herr_t H5S_point_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, void *operator_data); +__DLL__ herr_t H5S_point_select_fill(const void *fill, size_t fill_size, + H5S_t *space, void *buf); /* "All" select functions */ __DLL__ herr_t H5S_all_release(H5S_t *space); @@ -159,6 +161,8 @@ __DLL__ herr_t H5S_all_write(H5F_t *f, const struct H5O_layout_t *layout, hid_t dxpl_id, const void *buf); __DLL__ herr_t H5S_all_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, void *operator_data); +__DLL__ herr_t H5S_all_select_fill(const void *fill, size_t fill_size, + H5S_t *space, void *buf); __DLL__ htri_t H5S_all_opt_possible(const H5S_t *mem_space, const H5S_t *file_space, const unsigned flags); @@ -179,6 +183,8 @@ __DLL__ htri_t H5S_hyper_select_single(const H5S_t *space); __DLL__ htri_t H5S_hyper_select_regular(const H5S_t *space); __DLL__ herr_t H5S_hyper_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, void *operator_data); +__DLL__ herr_t H5S_hyper_select_fill(const void *fill, size_t fill_size, + H5S_t *space, void *buf); /* "None" selection functions */ __DLL__ herr_t H5S_select_none(H5S_t *space); diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 7ca1bed..883dfae 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -520,11 +520,11 @@ H5S_point_mgath (const void *_buf, size_t elmt_size, #ifdef QAK printf("%s: check 1.0\n",FUNC); #endif /* QAK */ - if ((space_ndims=H5S_get_simple_extent_dims (mem_space, mem_size, NULL))<0) { - HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, 0, - "unable to retrieve data space dimensions"); - } + /* Get the dataspace dimensions */ + if ((space_ndims=H5S_get_simple_extent_dims (mem_space, mem_size, NULL))<0) + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, 0, "unable to retrieve data space dimensions"); + /* Loop through all the points selected */ for(num_gath=0; num_gathpnt.elmt_left>0) { /* Compute the location of the point to get */ @@ -596,17 +596,11 @@ H5S_point_mscat (const void *_tconv_buf, size_t elmt_size, #ifdef QAK printf("%s: check 1.0\n",FUNC); #endif /* QAK */ - /* - * Retrieve hyperslab information to determine what elements are being - * selected (there might be other selection methods in the future). We - * only handle hyperslabs with unit sample because there's currently no - * way to pass sample information to H5V_hyper_copy(). - */ - if ((space_ndims=H5S_get_simple_extent_dims (mem_space, mem_size, NULL))<0) { - HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, - "unable to retrieve data space dimensions"); - } + /* Get the dataspace dimensions */ + if ((space_ndims=H5S_get_simple_extent_dims (mem_space, mem_size, NULL))<0) + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to retrieve data space dimensions"); + /* Loop through all the points selected */ for(num_scat=0; num_scatpnt.elmt_left>0) { /* Compute the location of the point to get */ @@ -1202,7 +1196,6 @@ H5S_point_select_regular(const H5S_t *space) else ret_value=FALSE; -done: FUNC_LEAVE (ret_value); } /* H5S_point_select_regular() */ @@ -1384,18 +1377,21 @@ done: COMMENTS, BUGS, ASSUMPTIONS EXAMPLES REVISION LOG + QAK - 2002/4/5 - Wasn't using selection offset in calculation, corrected. --------------------------------------------------------------------------*/ herr_t H5S_point_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, void *operator_data) { - hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Dataspace size */ - hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* Point offset */ - hsize_t offset; /* offset of region in buffer */ - void *tmp_buf; /* temporary location of the element in the buffer */ + hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Dataspace size */ + hsize_t acc; /* Size accumulator */ + hsize_t offset; /* Offset of region in buffer */ + hsize_t elmt_size; /* Size of datatype */ + void *tmp_buf; /* Temporary location of the element in the buffer */ H5S_pnt_node_t *node; /* Point node */ - unsigned rank; /* Dataspace rank */ - H5T_t *dt; /* Datatype structure */ + unsigned rank; /* Dataspace rank */ + H5T_t *dt; /* Datatype structure */ + int i; /* Index variable */ herr_t ret_value=0; /* return value */ FUNC_ENTER (H5S_point_select_iterate, 0); @@ -1414,17 +1410,18 @@ H5S_point_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t /* Set the size of the datatype */ if (NULL==(dt=H5I_object(type_id))) HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype"); - mem_size[rank]=H5T_get_size(dt); + mem_size[rank]=elmt_size=H5T_get_size(dt); /* Iterate through the node, checking the bounds on each element */ node=space->select.sel_info.pnt_lst->head; while(node!=NULL && ret_value==0) { - /* Set up the location of the point */ - HDmemcpy(mem_offset, node->pnt, rank*sizeof(hssize_t)); - mem_offset[rank]=0; + /* Compute the offset of each selected point in the buffer */ + for(i=rank-1,acc=elmt_size,offset=0; i>=0; i--) { + offset+=(node->pnt[i]+space->select.offset[i])*acc; + acc*=mem_size[i]; + } /* end for */ /* Get the offset in the memory buffer */ - offset=H5V_array_offset(rank+1,mem_size,(const hssize_t *)mem_offset); tmp_buf=((char *)buf+offset); ret_value=(*op)(tmp_buf,type_id,(hsize_t)rank,node->pnt,operator_data); @@ -1434,3 +1431,75 @@ H5S_point_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t FUNC_LEAVE (ret_value); } /* H5S_point_select_iterate() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_point_select_fill + PURPOSE + Fill a point selection in memory with a value + USAGE + herr_t H5S_point_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_point_select_fill(const void *fill, size_t fill_size, H5S_t *space, void *_buf) +{ + hsize_t size[H5O_LAYOUT_NDIMS]; /* Total size of memory buf */ + uint8_t *buf=(uint8_t *)_buf; /* Alias for memory buffer */ + hsize_t acc; /* Coordinate accumulator */ + hsize_t off; /* Coordinate offset */ + H5S_pnt_node_t *node; /* Point node */ + int ndims; /* Dimensionality of space*/ + int i; /* Index variable */ + herr_t ret_value=SUCCEED; /* return value */ + + FUNC_ENTER (H5S_point_select_fill, FAIL); + + /* Check args */ + assert(fill); + assert(fill_size>0); + assert(space); + assert(buf); + + /* Fill the selection in the memory buffer */ + + /* Get the dataspace dimensions */ + if ((ndims=H5S_get_simple_extent_dims (space, size, NULL))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to retrieve data space dimensions"); + + /* Loop through all the points selected */ + node=space->select.sel_info.pnt_lst->head; + while(node!=NULL) { + /* Compute the offset of each selected point in the buffer */ + for(i=ndims-1,acc=fill_size,off=0; i>=0; i--) { + off+=(node->pnt[i]+space->select.offset[i])*acc; + acc*=size[i]; + } /* end for */ + + /* Set the selected point to the fill value */ + HDmemcpy(buf+off,fill,fill_size); + + /* Advance to the next point */ + node=node->next; + } /* end while */ + +done: + FUNC_LEAVE (ret_value); +} /* H5S_point_select_fill() */ + diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 5af635d..0380d36 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -223,6 +223,8 @@ __DLL__ herr_t H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, void *operator_data); __DLL__ herr_t H5S_sel_iter_release(const H5S_t *space, H5S_sel_iter_t *sel_iter); +__DLL__ herr_t H5S_select_fill(const void *fill, size_t fill_size, H5S_t *space, + void *buf); #ifdef H5_HAVE_PARALLEL diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 92f9832..8d18e5c 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -1220,7 +1220,7 @@ H5S_select_contiguous(const H5S_t *space) /*-------------------------------------------------------------------------- NAME - H5S_iterate + H5S_select_iterate PURPOSE Iterate over the selected elements in a memory buffer. USAGE @@ -1536,7 +1536,72 @@ H5S_select_regular(const H5S_t *space) break; } /* end switch */ -done: FUNC_LEAVE (ret_value); } /* H5S_select_regular() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_select_fill + PURPOSE + Fill a selection in memory with a value + USAGE + herr_t H5S_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_select_fill(const void *fill, size_t fill_size, H5S_t *space, void *buf) +{ + herr_t ret_value=FAIL; /* return value */ + + FUNC_ENTER (H5S_select_fill, FAIL); + + /* Check args */ + assert(fill); + assert(fill_size>0); + assert(space); + assert(buf); + + /* Fill the selection in the memory buffer */ + /* [Defer (mostly) to the selection routines] */ + switch(space->select.type) { + case H5S_SEL_POINTS: /* Sequence of points selected */ + ret_value=H5S_point_select_fill(fill,fill_size,space,buf); + break; + + case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */ + ret_value=H5S_hyper_select_fill(fill,fill_size,space,buf); + break; + + case H5S_SEL_ALL: /* Entire extent selected */ + ret_value=H5S_all_select_fill(fill,fill_size,space,buf); + break; + + case H5S_SEL_NONE: /* Nothing selected */ + ret_value=SUCCEED; + break; + + case H5S_SEL_ERROR: + case H5S_SEL_N: + assert(0 && "Invalid selection type!"); + break; + } /* end switch */ + + FUNC_LEAVE (ret_value); +} /* H5S_select_fill() */ + diff --git a/src/H5V.c b/src/H5V.c index d4ac850..50b937f 100644 --- a/src/H5V.c +++ b/src/H5V.c @@ -80,6 +80,9 @@ H5V_stride_optimize1(unsigned *np/*in,out*/, hsize_t *elmt_size/*in,out*/, * Saturday, October 11, 1997 * * Modifications: + * Unrolled loops for common cases + * Quincey Koziol + * ?, ? ?, 2001? * *------------------------------------------------------------------------- */ @@ -224,6 +227,9 @@ H5V_stride_optimize2(unsigned *np/*in,out*/, hsize_t *elmt_size/*in,out*/, * Saturday, October 11, 1997 * * Modifications: + * Unrolled loops for common cases + * Quincey Koziol + * ?, ? ?, 2001? * *------------------------------------------------------------------------- */ @@ -491,6 +497,9 @@ H5V_hyper_fill(unsigned n, const hsize_t *_size, * Friday, October 10, 1997 * * Modifications: + * Unrolled loops for common cases + * Quincey Koziol + * ?, ? ?, 2001? * *------------------------------------------------------------------------- */ @@ -901,13 +910,11 @@ H5V_array_fill(void *_dst, const void *src, size_t size, size_t count) * Purpose: Given a coordinate description of a location in an array, this * function returns the byte offset of the coordinate. * - * The dimensionality of the whole array, the hyperslab, and the - * returned stride array is N. The whole array dimensions are - * TOTAL_SIZE and the coordinate is at offset OFFSET. - * - * Return: Success: Byte offset from beginning of array to start - * of striding. + * The dimensionality of the whole array, and the offset is N. + * The whole array dimensions are TOTAL_SIZE and the coordinate + * is at offset OFFSET. * + * Return: Success: Byte offset from beginning of array to element offset * Failure: abort() -- should never fail * * Programmer: Quincey Koziol @@ -924,7 +931,7 @@ H5V_array_offset(unsigned n, const hsize_t *total_size, const hssize_t *offset) hsize_t acc; /*accumulator */ int i; /*counter */ - FUNC_ENTER(H5V_array_stride, (HDabort(), 0)); + FUNC_ENTER(H5V_array_offset, (HDabort(), 0)); assert(n <= H5V_HYPER_NDIMS); assert(total_size); @@ -934,8 +941,8 @@ H5V_array_offset(unsigned n, const hsize_t *total_size, const hssize_t *offset) for (i=(int)(n-1), acc=1, skip=0; i>=0; --i) { skip += acc * offset[i]; acc *= total_size[i]; - } + } /* end for */ FUNC_LEAVE(skip); -} +} /* end H5V_array_offset() */ diff --git a/test/tselect.c b/test/tselect.c index d0454d6..f439c96 100644 --- a/test/tselect.c +++ b/test/tselect.c @@ -4075,6 +4075,9 @@ test_select_combine(void) hsize_t blocks[128][2][SPACE7_RANK]; /* List of blocks */ herr_t error; + /* Output message about test being performed */ + MESSAGE(5, ("Testing Selection Combinations\n")); + /* Create dataspace for dataset on disk */ base_id = H5Screate_simple(SPACE7_RANK, dims, NULL); CHECK(base_id, FAIL, "H5Screate_simple"); @@ -4409,6 +4412,423 @@ test_select_combine(void) /**************************************************************** ** +** test_select_fill_all(): Test basic H5S (dataspace) selection code. +** Tests filling "all" selections +** +****************************************************************/ +static void +test_select_fill_all(void) +{ + hid_t sid1; /* Dataspace ID */ + hsize_t dims1[] = {SPACE7_DIM1, SPACE7_DIM2}; + int fill_value; /* Fill value */ + unsigned short *wbuf, /* buffer to write to disk */ + *tbuf; /* temporary buffer pointer */ + int i,j; /* Counters */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Filling 'all' Selections\n")); + + /* Allocate memory buffer */ + wbuf=malloc(sizeof(unsigned short)*SPACE7_DIM1*SPACE7_DIM2); + + /* Initialize memory buffer */ + for(i=0, tbuf=wbuf; i=(int)(start[0]+real_offset[0]) && i<(int)(start[0]+count[0]+real_offset[0])) + && (j>=(int)(start[1]+real_offset[1]) && j<(int)(start[1]+count[1]+real_offset[1]))) { + if(*tbuf!=(unsigned short)fill_value) { + num_errs++; + printf("Error! j=%d, i=%d, *tbuf=%u, fill_value=%u\n",j,i,(unsigned)*tbuf,(unsigned)fill_value); + } /* end if */ + } /* end if */ + else { + if(*tbuf!=((unsigned short)(i*SPACE7_DIM2)+j)) { + num_errs++; + printf("Error! j=%d, i=%d, *tbuf=%u, should be: %u\n",j,i,(unsigned)*tbuf,(unsigned)((i*SPACE7_DIM2)+j)); + } /* end if */ + } /* end else */ + } /* end for */ + + /* Free memory buffers */ + free(wbuf); +} /* test_select_fill_hyper_simple() */ + +/**************************************************************** +** +** test_select_fill_hyper_regular(): Test basic H5S (dataspace) selection code. +** Tests filling "regular" (i.e. strided block) hyperslab selections +** +****************************************************************/ +static void +test_select_fill_hyper_regular(hssize_t *offset) +{ + hid_t sid1; /* Dataspace ID */ + hsize_t dims1[] = {SPACE7_DIM1, SPACE7_DIM2}; + hssize_t real_offset[SPACE7_RANK]; /* Actual offset to use */ + hssize_t start[SPACE7_RANK]; /* Hyperslab start */ + hsize_t stride[SPACE7_RANK]; /* Hyperslab stride size */ + hsize_t count[SPACE7_RANK]; /* Hyperslab block count */ + hsize_t block[SPACE7_RANK]; /* Hyperslab block size */ + hssize_t points[16][SPACE7_RANK] = { + {2,2}, {2,3}, {3,2}, {3,3}, + {2,6}, {2,7}, {3,6}, {3,7}, + {6,2}, {6,3}, {7,2}, {7,3}, + {6,6}, {6,7}, {7,6}, {7,7}, + }; + size_t num_points=16; /* Number of points selected */ + int fill_value; /* Fill value */ + unsigned short *wbuf, /* buffer to write to disk */ + *tbuf; /* temporary buffer pointer */ + int i,j,k; /* Counters */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Filling Regular 'hyperslab' Selections\n")); + + /* Allocate memory buffer */ + wbuf=malloc(sizeof(unsigned short)*SPACE7_DIM1*SPACE7_DIM2); + + /* Initialize memory buffer */ + for(i=0, tbuf=wbuf; i