summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2000-09-13 21:58:18 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2000-09-13 21:58:18 (GMT)
commit1f109221dffd39ca93470923b32eb2a13ccb5715 (patch)
tree296f00b85e2aab5c5100a585af8074525b4fd1d6 /src
parent683a11a633bb78695714f981d40a0265fdd81154 (diff)
downloadhdf5-1f109221dffd39ca93470923b32eb2a13ccb5715.zip
hdf5-1f109221dffd39ca93470923b32eb2a13ccb5715.tar.gz
hdf5-1f109221dffd39ca93470923b32eb2a13ccb5715.tar.bz2
[svn-r2544] Optimized regular hyperslab I/O routines and data structures. On my benchmarks,
they are about 4-5 times faster than before. We no longer generate "general" hyperslab data structures for regular hyperslabs, the general data structures are only generated when needed for irregular hyperslabs. Still fixing a couple of nook-and-cranny functions to understand the new information for the regular hyperslabs, so the tests aren't completely passing, but I wanted to get this checked in for Elena's benchmarks. I should have more/all tests passing later today.
Diffstat (limited to 'src')
-rw-r--r--src/H5Shyper.c2060
-rw-r--r--src/H5Sselect.c138
2 files changed, 1886 insertions, 312 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index c140e70..4348c82 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -60,8 +60,18 @@ static H5S_hyper_region_t * H5S_hyper_get_regions (size_t *num_regions,
uintn rank, uintn dim, size_t bound_count,
H5S_hyper_bound_t **lo_bounds, hssize_t *pos, hssize_t *offset);
static size_t H5S_hyper_fread (intn dim, H5S_hyper_io_info_t *io_info);
+static size_t H5S_hyper_fread_opt (H5F_t *f, const struct H5O_layout_t *layout,
+ const struct H5O_pline_t *pline, const struct H5O_fill_t *fill,
+ const struct H5O_efl_t *efl, size_t elmt_size,
+ const H5S_t *file_space, H5S_sel_iter_t *file_iter,
+ size_t nelmts, hid_t dxpl_id, void *_buf/*out*/);
static size_t H5S_hyper_fwrite (intn dim,
H5S_hyper_io_info_t *io_info);
+static size_t H5S_hyper_fwrite_opt (H5F_t *f, const struct H5O_layout_t *layout,
+ const struct H5O_pline_t *pline, const struct H5O_fill_t *fill,
+ const struct H5O_efl_t *efl, size_t elmt_size,
+ const H5S_t *file_space, H5S_sel_iter_t *file_iter,
+ size_t nelmts, hid_t dxpl_id, const void *_buf);
static herr_t H5S_hyper_init (const struct H5O_layout_t *layout,
const H5S_t *space, H5S_sel_iter_t *iter, size_t *min_elem_out);
static size_t H5S_hyper_favail (const H5S_t *space, const H5S_sel_iter_t *iter,
@@ -80,10 +90,18 @@ static herr_t H5S_hyper_fscat (H5F_t *f, const struct H5O_layout_t *layout,
const H5S_t *file_space,
H5S_sel_iter_t *file_iter, size_t nelmts,
hid_t dxpl_id, const void *buf);
+static size_t H5S_hyper_mread (intn dim, H5S_hyper_io_info_t *io_info);
+static herr_t H5S_hyper_mread_opt (const void *_buf, size_t elmt_size,
+ const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
+ size_t nelmts, void *_tconv_buf/*out*/);
static size_t H5S_hyper_mgath (const void *_buf, size_t elmt_size,
const H5S_t *mem_space,
H5S_sel_iter_t *mem_iter, size_t nelmts,
void *_tconv_buf/*out*/);
+static size_t H5S_hyper_mwrite (intn dim, H5S_hyper_io_info_t *io_info);
+static herr_t H5S_hyper_mwrite_opt (const void *_tconv_buf, size_t elmt_size,
+ const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
+ size_t nelmts, void *_buf/*out*/);
static herr_t H5S_hyper_mscat (const void *_tconv_buf, size_t elmt_size,
const H5S_t *mem_space,
H5S_sel_iter_t *mem_iter, size_t nelmts,
@@ -808,6 +826,338 @@ H5S_hyper_fread (intn dim, H5S_hyper_io_info_t *io_info)
/*-------------------------------------------------------------------------
+ * Function: H5S_hyper_iter_next
+ *
+ * Purpose: Moves a hyperslab iterator to the beginning of the next sequence
+ * of elements to read. Handles walking off the end in all dimensions.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, September 8, 2000
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5S_hyper_iter_next (const H5S_t *file_space, H5S_sel_iter_t *file_iter)
+{
+ hssize_t iter_offset[H5O_LAYOUT_NDIMS];
+ hssize_t iter_count[H5O_LAYOUT_NDIMS];
+ intn fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ intn temp_dim; /* Temporary rank holder */
+ intn i; /* Counters */
+ uintn ndims; /* Number of dimensions of dataset */
+ size_t num_read=0; /* Number of elements read */
+
+ FUNC_ENTER (H5S_hyper_iter_next, FAIL);
+
+ /* Set some useful rank information */
+ fast_dim=file_space->extent.u.simple.rank-1;
+ ndims=file_space->extent.u.simple.rank;
+
+ /* Calculate the offset and block count for each dimension */
+ for(i=0; i<ndims; i++) {
+ iter_offset[i]=(file_iter->hyp.pos[i]-file_space->select.sel_info.hslab.diminfo[i].start)%file_space->select.sel_info.hslab.diminfo[i].stride;
+ iter_count[i]=(file_iter->hyp.pos[i]-file_space->select.sel_info.hslab.diminfo[i].start)/file_space->select.sel_info.hslab.diminfo[i].stride;
+ } /* end for */
+
+ /* Start with the fastest changing dimension */
+ temp_dim=fast_dim;
+ while(temp_dim>=0) {
+ if(temp_dim==fast_dim) {
+ /* Move to the next block in the current dimension */
+ iter_offset[temp_dim]=0; /* reset the offset in the fastest dimension */
+ iter_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(iter_count[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else
+ iter_count[temp_dim]=0; /* reset back to the beginning of the line */
+ } /* end if */
+ else {
+ /* Move to the next row in the curent dimension */
+ iter_offset[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(iter_offset[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ iter_offset[temp_dim]=0;
+ iter_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(iter_count[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else
+ iter_count[temp_dim]=0; /* reset back to the beginning of the line */
+ } /* end else */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+
+ /* Translate current iter_offset and iter_count into iterator position */
+ for(i=0; i<ndims; i++)
+ file_iter->hyp.pos[i]=file_space->select.sel_info.hslab.diminfo[i].start+(file_space->select.sel_info.hslab.diminfo[i].stride*iter_count[i])+iter_offset[i];
+
+ FUNC_LEAVE (SUCCEED);
+} /* H5S_hyper_iter_next() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_hyper_fread_opt
+ *
+ * Purpose: Performs an optimized gather from the file, based on a regular
+ * hyperslab (i.e. one which was generated from just one call to
+ * H5Sselect_hyperslab).
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Friday, September 8, 2000
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5S_hyper_fread_opt (H5F_t *f, const struct H5O_layout_t *layout,
+ const struct H5O_pline_t *pline,
+ const struct H5O_fill_t *fill,
+ const struct H5O_efl_t *efl, size_t elmt_size,
+ const H5S_t *file_space, H5S_sel_iter_t *file_iter,
+ size_t nelmts, hid_t dxpl_id, void *_buf/*out*/)
+{
+ hsize_t hsize[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
+ hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */
+ hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset on disk */
+ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary block count */
+ hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block offset */
+ uint8_t *buf=(uint8_t *)_buf; /* Alias for pointer arithmetic */
+ intn fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ intn temp_dim; /* Temporary rank holder */
+ intn i; /* Counters */
+ uintn ndims; /* Number of dimensions of dataset */
+ intn actual_read; /* The actual number of elements to read in */
+ size_t num_read=0; /* Number of elements read */
+
+ FUNC_ENTER (H5S_hyper_fread_opt, 0);
+
+#ifdef QAK
+printf("%s: Called!\n",FUNC);
+#endif /* QAK */
+ /* Check if this is the first element read in from the hyperslab */
+ if(file_iter->hyp.pos[0]==(-1)) {
+ for(i=0; i<file_space->extent.u.simple.rank; i++)
+ file_iter->hyp.pos[i]=file_space->select.sel_info.hslab.diminfo[i].start;
+ } /* end if */
+
+#ifdef QAK
+for(i=0; i<file_space->extent.u.simple.rank; i++)
+ printf("%s: file_file->hyp.pos[%d]=%d\n",FUNC,(int)i,(int)file_iter->hyp.pos[i]);
+#endif /* QAK */
+
+ /* Set the rank of the fastest changing dimension */
+ fast_dim=file_space->extent.u.simple.rank-1;
+
+ /* Set up the hyperslab and 'zero' arrays */
+ ndims=file_space->extent.u.simple.rank;
+ /* initialize hyperslab size and offset in memory buffer */
+ for(i=0; i<(int)(ndims+1); i++) {
+ hsize[i]=1; /* hyperslab size is 1, except for last element */
+ zero[i]=0; /* memory offset is 0 */
+ } /* end for */
+ hsize[ndims] = elmt_size;
+
+ /* Check if we stopped in the middle of a sequence of elements */
+ if((file_iter->hyp.pos[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start)%file_space->select.sel_info.hslab.diminfo[fast_dim].stride!=0) {
+ intn leftover; /* The number of elements left over from the last sequence */
+
+#ifdef QAK
+printf("%s: Check 1.0\n",FUNC);
+#endif /* QAK */
+ /* Calculate the number of elements left in the sequence */
+ leftover=file_space->select.sel_info.hslab.diminfo[fast_dim].block-((file_iter->hyp.pos[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start)%file_space->select.sel_info.hslab.diminfo[fast_dim].stride);
+
+ /* Make certain that we don't read too many */
+ actual_read=MIN(leftover,nelmts);
+
+ /* Set the hyperslab size in the fastest changing dimension to read in */
+ hsize[fast_dim]=actual_read;
+
+ /* Copy the location of the point to get */
+ HDmemcpy(offset, file_iter->hyp.pos,ndims*sizeof(hssize_t));
+ offset[ndims] = 0;
+
+ /* Add in the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] += file_space->select.offset[i];
+
+ /* Read in the rest of the sequence, if possible */
+ if (H5F_arr_read(f, dxpl_id, layout, pline, fill, efl, hsize,
+ hsize, zero, offset, buf/*out*/)<0) {
+ HRETURN_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
+ }
+
+ /* Increment the offset of the buffer */
+ buf+=elmt_size*actual_read;
+
+ /* Increment the count read */
+ num_read+=actual_read;
+
+ /* Decrement the number of elements left in selection */
+ file_iter->hyp.elmt_left-=actual_read;
+
+ /* Advance the point iterator */
+ /* If we had enough buffer space to read in the rest of the sequence
+ * in the fastest changing dimension, move the iterator offset to
+ * the beginning of the next block to read. Otherwise, just advance
+ * the iterator in the fastest changing dimension.
+ */
+ if(actual_read==leftover) {
+ /* Move iterator offset to beginning of next sequence in the fastest changing dimension */
+ H5S_hyper_iter_next(file_space,file_iter);
+ } /* end if */
+ else {
+ file_iter->hyp.pos[fast_dim]+=actual_read; /* whole sequence not read in, just advance fastest dimension offset */
+ } /* end if */
+ } /* end if */
+
+ /* Now that we've cleared the "remainder" of the previous fastest dimension
+ * sequence, we must be at the beginning of a sequence, so use the fancy
+ * algorithm to compute the offsets and run through as many as possible,
+ * until the buffer fills up.
+ */
+ if(num_read<nelmts) { /* Just in case the "remainder" aboce filled the buffer */
+#ifdef QAK
+printf("%s: Check 2.0\n",FUNC);
+#endif /* QAK */
+ /* Compute the arrays to perform I/O on */
+ /* Copy the location of the point to get */
+ HDmemcpy(offset, file_iter->hyp.pos,ndims*sizeof(hssize_t));
+ offset[ndims] = 0;
+
+ /* Add in the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] += file_space->select.offset[i];
+
+ /* Compute the current "counts" for this location */
+ for(i=0; i<ndims; i++) {
+ tmp_count[i] = (file_iter->hyp.pos[i]-file_space->select.sel_info.hslab.diminfo[i].start)%file_space->select.sel_info.hslab.diminfo[i].stride;
+ tmp_block[i] = (file_iter->hyp.pos[i]-file_space->select.sel_info.hslab.diminfo[i].start)/file_space->select.sel_info.hslab.diminfo[i].stride;
+ } /* end for */
+
+ /* Set the number of elements to read each time */
+ actual_read=file_space->select.sel_info.hslab.diminfo[fast_dim].block;
+ hsize[fast_dim]=actual_read;
+#ifdef QAK
+printf("%s: actual_read=%d\n",FUNC,(int)actual_read);
+for(i=0; i<file_space->extent.u.simple.rank; i++)
+ printf("%s: diminfo: start[%d]=%d, stride[%d]=%d, block[%d]=%d, count[%d]=%d\n",FUNC,
+ (int)i,(int)file_space->select.sel_info.hslab.diminfo[i].start,
+ (int)i,(int)file_space->select.sel_info.hslab.diminfo[i].stride,
+ (int)i,(int)file_space->select.sel_info.hslab.diminfo[i].block,
+ (int)i,(int)file_space->select.sel_info.hslab.diminfo[i].count);
+#endif /* QAK */
+
+ /* Read in data until an entire sequence can't be read in any longer */
+ while(num_read<nelmts) {
+ /* Check if we are running out of room in the buffer */
+ if((actual_read+num_read)>nelmts) {
+ actual_read=nelmts-num_read;
+ hsize[fast_dim]=actual_read;
+ } /* end if */
+
+#ifdef QAK
+printf("%s: num_read=%d\n",FUNC,(int)num_read);
+for(i=0; i<file_space->extent.u.simple.rank; i++)
+ printf("%s: tmp_count[%d]=%d, offset[%d]=%d\n",FUNC,(int)i,(int)tmp_count[i],(int)i,(int)offset[i]);
+#endif /* QAK */
+
+ /* Read in the sequence, if possible */
+ if (H5F_arr_read(f, dxpl_id, layout, pline, fill, efl, hsize,
+ hsize, zero, offset, buf/*out*/)<0) {
+ HRETURN_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
+ }
+
+ /* Increment the offset of the buffer */
+ buf+=elmt_size*actual_read;
+
+ /* Increment the count read */
+ num_read+=actual_read;
+
+ /* Decrement the number of elements left in selection */
+ file_iter->hyp.elmt_left-=actual_read;
+
+ /* Increment the offset and count */
+ temp_dim=fast_dim;
+ while(temp_dim>=0) {
+ if(temp_dim==fast_dim) {
+ /* Move to the next block in the current dimension */
+ /* Check for partial block read! */
+ if(actual_read<file_space->select.sel_info.hslab.diminfo[fast_dim].block) {
+ offset[temp_dim]+=actual_read;
+ break;
+ } /* end if */
+ else {
+ offset[temp_dim]+=file_space->select.sel_info.hslab.diminfo[temp_dim].stride; /* reset the offset in the fastest dimension */
+ tmp_count[temp_dim]++;
+ } /* end else */
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else {
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ offset[temp_dim]=file_space->select.sel_info.hslab.diminfo[temp_dim].start+file_space->select.offset[temp_dim];
+ } /* end else */
+ } /* end if */
+ else {
+ /* Move to the next row in the curent dimension */
+ offset[temp_dim]++;
+ tmp_block[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_block[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ offset[temp_dim]+=(file_space->select.sel_info.hslab.diminfo[temp_dim].stride-file_space->select.sel_info.hslab.diminfo[temp_dim].block);
+ tmp_block[temp_dim]=0;
+ tmp_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else {
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ tmp_block[temp_dim]=0;
+ offset[temp_dim]=file_space->select.sel_info.hslab.diminfo[temp_dim].start+file_space->select.offset[temp_dim];
+ }
+ } /* end else */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+ } /* end while */
+
+ /* Update the iterator with the location we stopped */
+ HDmemcpy(file_iter->hyp.pos, offset, ndims*sizeof(hssize_t));
+ } /* end if */
+
+ FUNC_LEAVE (num_read);
+} /* H5S_hyper_fread_opt() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5S_hyper_fgath
*
* Purpose: Gathers data points from file F and accumulates them in the
@@ -859,31 +1209,39 @@ H5S_hyper_fgath (H5F_t *f, const struct H5O_layout_t *layout,
printf("%s: check 1.0\n", FUNC);
#endif /* QAK */
- /* Initialize parameter block for recursive calls */
- io_info.f=f;
- io_info.layout=layout;
- io_info.pline=pline;
- io_info.fill=fill;
- io_info.efl=efl;
- io_info.elmt_size=elmt_size;
- io_info.space=file_space;
- io_info.iter=file_iter;
- io_info.nelmts=nelmts;
- io_info.dxpl_id = dxpl_id;
- io_info.src=NULL;
- io_info.dst=_buf;
-
- /* Set the hyperslab size to copy */
- io_info.hsize[0]=1;
- H5V_array_fill(io_info.hsize,io_info.hsize,sizeof(io_info.hsize[0]),file_space->extent.u.simple.rank);
- io_info.hsize[file_space->extent.u.simple.rank]=elmt_size;
-
- /* Recursively input the hyperslabs currently defined */
- /* starting with the slowest changing dimension */
- num_read=H5S_hyper_fread(-1,&io_info);
+ /* Check for the special case of just one H5Sselect_hyperslab call made */
+ if(file_space->select.sel_info.hslab.diminfo!=NULL) {
+ /* Use optimized call to read in regular hyperslab */
+ num_read=H5S_hyper_fread_opt(f,layout,pline,fill,efl,elmt_size,file_space,file_iter,nelmts,dxpl_id,_buf);
+ } /* end if */
+ /* Perform generic hyperslab operation */
+ else {
+ /* Initialize parameter block for recursive calls */
+ io_info.f=f;
+ io_info.layout=layout;
+ io_info.pline=pline;
+ io_info.fill=fill;
+ io_info.efl=efl;
+ io_info.elmt_size=elmt_size;
+ io_info.space=file_space;
+ io_info.iter=file_iter;
+ io_info.nelmts=nelmts;
+ io_info.dxpl_id = dxpl_id;
+ io_info.src=NULL;
+ io_info.dst=_buf;
+
+ /* Set the hyperslab size to copy */
+ io_info.hsize[0]=1;
+ H5V_array_fill(io_info.hsize,io_info.hsize,sizeof(io_info.hsize[0]),file_space->extent.u.simple.rank);
+ io_info.hsize[file_space->extent.u.simple.rank]=elmt_size;
+
+ /* Recursively input the hyperslabs currently defined */
+ /* starting with the slowest changing dimension */
+ num_read=H5S_hyper_fread(-1,&io_info);
#ifdef QAK
- printf("%s: check 5.0, num_read=%d\n",FUNC,(int)num_read);
+ printf("%s: check 5.0, num_read=%d\n",FUNC,(int)num_read);
#endif /* QAK */
+ } /* end else */
FUNC_LEAVE (ret_value==SUCCEED ? num_read : 0);
} /* H5S_hyper_fgath() */
@@ -1053,6 +1411,253 @@ H5S_hyper_fwrite (intn dim, H5S_hyper_io_info_t *io_info)
/*-------------------------------------------------------------------------
+ * Function: H5S_hyper_fwrite_opt
+ *
+ * Purpose: Performs an optimized scatter to the file, based on a regular
+ * hyperslab (i.e. one which was generated from just one call to
+ * H5Sselect_hyperslab).
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, September 12, 2000
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5S_hyper_fwrite_opt (H5F_t *f, const struct H5O_layout_t *layout,
+ const struct H5O_pline_t *pline,
+ const struct H5O_fill_t *fill,
+ const struct H5O_efl_t *efl, size_t elmt_size,
+ const H5S_t *file_space, H5S_sel_iter_t *file_iter,
+ size_t nelmts, hid_t dxpl_id, const void *_buf)
+{
+ hsize_t hsize[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
+ hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */
+ hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset on disk */
+ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary block count */
+ hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block offset */
+ const uint8_t *buf=(const uint8_t *)_buf; /* Alias for pointer arithmetic */
+ intn fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ intn temp_dim; /* Temporary rank holder */
+ intn i; /* Counters */
+ uintn ndims; /* Number of dimensions of dataset */
+ intn actual_write; /* The actual number of elements to read in */
+ size_t num_write=0; /* Number of elements read */
+
+ FUNC_ENTER (H5S_hyper_fwrite_opt, 0);
+
+#ifdef QAK
+printf("%s: Called!\n",FUNC);
+#endif /* QAK */
+ /* Check if this is the first element read in from the hyperslab */
+ if(file_iter->hyp.pos[0]==(-1)) {
+ for(i=0; i<file_space->extent.u.simple.rank; i++)
+ file_iter->hyp.pos[i]=file_space->select.sel_info.hslab.diminfo[i].start;
+ } /* end if */
+
+#ifdef QAK
+for(i=0; i<file_space->extent.u.simple.rank; i++)
+ printf("%s: file_file->hyp.pos[%d]=%d\n",FUNC,(int)i,(int)file_iter->hyp.pos[i]);
+#endif /* QAK */
+
+ /* Set the rank of the fastest changing dimension */
+ fast_dim=file_space->extent.u.simple.rank-1;
+
+ /* Set up the hyperslab and 'zero' arrays */
+ ndims=file_space->extent.u.simple.rank;
+ /* initialize hyperslab size and offset in memory buffer */
+ for(i=0; i<(int)(ndims+1); i++) {
+ hsize[i]=1; /* hyperslab size is 1, except for last element */
+ zero[i]=0; /* memory offset is 0 */
+ } /* end for */
+ hsize[ndims] = elmt_size;
+
+ /* Check if we stopped in the middle of a sequence of elements */
+ if((file_iter->hyp.pos[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start)%file_space->select.sel_info.hslab.diminfo[fast_dim].stride!=0) {
+ intn leftover; /* The number of elements left over from the last sequence */
+
+#ifdef QAK
+printf("%s: Check 1.0\n",FUNC);
+#endif /* QAK */
+ /* Calculate the number of elements left in the sequence */
+ leftover=file_space->select.sel_info.hslab.diminfo[fast_dim].block-((file_iter->hyp.pos[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start)%file_space->select.sel_info.hslab.diminfo[fast_dim].stride);
+
+ /* Make certain that we don't write too many */
+ actual_write=MIN(leftover,nelmts);
+
+ /* Set the hyperslab size in the fastest changing dimension to write in */
+ hsize[fast_dim]=actual_write;
+
+ /* Copy the location of the point to get */
+ HDmemcpy(offset, file_iter->hyp.pos,ndims*sizeof(hssize_t));
+ offset[ndims] = 0;
+
+ /* Add in the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] += file_space->select.offset[i];
+
+ /* Read in the rest of the sequence, if possible */
+ if (H5F_arr_write(f, dxpl_id, layout, pline, fill, efl, hsize,
+ hsize, zero, offset, buf)<0) {
+ HRETURN_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "write error");
+ }
+
+ /* Increment the offset of the buffer */
+ buf+=elmt_size*actual_write;
+
+ /* Increment the count write */
+ num_write+=actual_write;
+
+ /* Decrement the number of elements left in selection */
+ file_iter->hyp.elmt_left-=actual_write;
+
+ /* Advance the point iterator */
+ /* If we had enough buffer space to write out the rest of the sequence
+ * in the fastest changing dimension, move the iterator offset to
+ * the beginning of the next block to write. Otherwise, just advance
+ * the iterator in the fastest changing dimension.
+ */
+ if(actual_write==leftover) {
+ /* Move iterator offset to beginning of next sequence in the fastest changing dimension */
+ H5S_hyper_iter_next(file_space,file_iter);
+ } /* end if */
+ else {
+ file_iter->hyp.pos[fast_dim]+=actual_write; /* whole sequence not written out, just advance fastest dimension offset */
+ } /* end if */
+ } /* end if */
+
+ /* Now that we've cleared the "remainder" of the previous fastest dimension
+ * sequence, we must be at the beginning of a sequence, so use the fancy
+ * algorithm to compute the offsets and run through as many as possible,
+ * until the buffer fills up.
+ */
+ if(num_write<nelmts) { /* Just in case the "remainder" aboce filled the buffer */
+#ifdef QAK
+printf("%s: Check 2.0\n",FUNC);
+#endif /* QAK */
+ /* Compute the arrays to perform I/O on */
+ /* Copy the location of the point to get */
+ HDmemcpy(offset, file_iter->hyp.pos,ndims*sizeof(hssize_t));
+ offset[ndims] = 0;
+
+ /* Add in the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] += file_space->select.offset[i];
+
+ /* Compute the current "counts" for this location */
+ for(i=0; i<ndims; i++) {
+ tmp_count[i] = (file_iter->hyp.pos[i]-file_space->select.sel_info.hslab.diminfo[i].start)%file_space->select.sel_info.hslab.diminfo[i].stride;
+ tmp_block[i] = (file_iter->hyp.pos[i]-file_space->select.sel_info.hslab.diminfo[i].start)/file_space->select.sel_info.hslab.diminfo[i].stride;
+ } /* end for */
+
+ /* Set the number of elements to write each time */
+ actual_write=file_space->select.sel_info.hslab.diminfo[fast_dim].block;
+ hsize[fast_dim]=actual_write;
+#ifdef QAK
+printf("%s: actual_write=%d\n",FUNC,(int)actual_write);
+for(i=0; i<file_space->extent.u.simple.rank; i++)
+ printf("%s: diminfo: start[%d]=%d, stride[%d]=%d, block[%d]=%d, count[%d]=%d\n",FUNC,
+ (int)i,(int)file_space->select.sel_info.hslab.diminfo[i].start,
+ (int)i,(int)file_space->select.sel_info.hslab.diminfo[i].stride,
+ (int)i,(int)file_space->select.sel_info.hslab.diminfo[i].block,
+ (int)i,(int)file_space->select.sel_info.hslab.diminfo[i].count);
+#endif /* QAK */
+
+ /* Read in data until an entire sequence can't be written out any longer */
+ while(num_write<nelmts) {
+ /* Check if we are running out of room in the buffer */
+ if((actual_write+num_write)>nelmts) {
+ actual_write=nelmts-num_write;
+ hsize[fast_dim]=actual_write;
+ } /* end if */
+
+#ifdef QAK
+printf("%s: num_write=%d\n",FUNC,(int)num_write);
+for(i=0; i<file_space->extent.u.simple.rank; i++)
+ printf("%s: tmp_count[%d]=%d, offset[%d]=%d\n",FUNC,(int)i,(int)tmp_count[i],(int)i,(int)offset[i]);
+#endif /* QAK */
+
+ /* Read in the sequence, if possible */
+ if (H5F_arr_write(f, dxpl_id, layout, pline, fill, efl, hsize,
+ hsize, zero, offset, buf)<0) {
+ HRETURN_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "write error");
+ }
+
+ /* Increment the offset of the buffer */
+ buf+=elmt_size*actual_write;
+
+ /* Increment the count write */
+ num_write+=actual_write;
+
+ /* Decrement the number of elements left in selection */
+ file_iter->hyp.elmt_left-=actual_write;
+
+ /* Increment the offset and count */
+ temp_dim=fast_dim;
+ while(temp_dim>=0) {
+ if(temp_dim==fast_dim) {
+ /* Move to the next block in the current dimension */
+ /* Check for partial block write! */
+ if(actual_write<file_space->select.sel_info.hslab.diminfo[fast_dim].block) {
+ offset[temp_dim]+=actual_write;
+ break;
+ } /* end if */
+ else {
+ offset[temp_dim]+=file_space->select.sel_info.hslab.diminfo[temp_dim].stride; /* reset the offset in the fastest dimension */
+ tmp_count[temp_dim]++;
+ } /* end else */
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else {
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ offset[temp_dim]=file_space->select.sel_info.hslab.diminfo[temp_dim].start+file_space->select.offset[temp_dim];
+ } /* end else */
+ } /* end if */
+ else {
+ /* Move to the next row in the curent dimension */
+ offset[temp_dim]++;
+ tmp_block[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_block[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ offset[temp_dim]+=(file_space->select.sel_info.hslab.diminfo[temp_dim].stride-file_space->select.sel_info.hslab.diminfo[temp_dim].block);
+ tmp_block[temp_dim]=0;
+ tmp_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else {
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ tmp_block[temp_dim]=0;
+ offset[temp_dim]=file_space->select.sel_info.hslab.diminfo[temp_dim].start+file_space->select.offset[temp_dim];
+ }
+ } /* end else */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+ } /* end while */
+
+ /* Update the iterator with the location we stopped */
+ HDmemcpy(file_iter->hyp.pos, offset, ndims*sizeof(hssize_t));
+ } /* end if */
+
+ FUNC_LEAVE (num_write);
+} /* H5S_hyper_fwrite_opt() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5S_hyper_fscat
*
* Purpose: Scatters dataset elements from the type conversion buffer BUF
@@ -1099,31 +1704,38 @@ H5S_hyper_fscat (H5F_t *f, const struct H5O_layout_t *layout,
printf("%s: check 1.0\n", FUNC);
#endif /* QAK */
- /* Initialize parameter block for recursive calls */
- io_info.f=f;
- io_info.layout=layout;
- io_info.pline=pline;
- io_info.fill=fill;
- io_info.efl=efl;
- io_info.elmt_size=elmt_size;
- io_info.space=file_space;
- io_info.iter=file_iter;
- io_info.nelmts=nelmts;
- io_info.dxpl_id = dxpl_id;
- io_info.src=_buf;
- io_info.dst=NULL;
-
- /* Set the hyperslab size to copy */
- io_info.hsize[0]=1;
- H5V_array_fill(io_info.hsize,io_info.hsize,sizeof(io_info.hsize[0]),file_space->extent.u.simple.rank);
- io_info.hsize[file_space->extent.u.simple.rank]=elmt_size;
-
- /* Recursively input the hyperslabs currently defined */
- /* starting with the slowest changing dimension */
- num_written=H5S_hyper_fwrite(-1,&io_info);
+ /* Check for the special case of just one H5Sselect_hyperslab call made */
+ if(file_space->select.sel_info.hslab.diminfo!=NULL) {
+ /* Use optimized call to write out regular hyperslab */
+ num_written=H5S_hyper_fwrite_opt(f,layout,pline,fill,efl,elmt_size,file_space,file_iter,nelmts,dxpl_id,_buf);
+ }
+ else {
+ /* Initialize parameter block for recursive calls */
+ io_info.f=f;
+ io_info.layout=layout;
+ io_info.pline=pline;
+ io_info.fill=fill;
+ io_info.efl=efl;
+ io_info.elmt_size=elmt_size;
+ io_info.space=file_space;
+ io_info.iter=file_iter;
+ io_info.nelmts=nelmts;
+ io_info.dxpl_id = dxpl_id;
+ io_info.src=_buf;
+ io_info.dst=NULL;
+
+ /* Set the hyperslab size to copy */
+ io_info.hsize[0]=1;
+ H5V_array_fill(io_info.hsize,io_info.hsize,sizeof(io_info.hsize[0]),file_space->extent.u.simple.rank);
+ io_info.hsize[file_space->extent.u.simple.rank]=elmt_size;
+
+ /* Recursively input the hyperslabs currently defined */
+ /* starting with the slowest changing dimension */
+ num_written=H5S_hyper_fwrite(-1,&io_info);
#ifdef QAK
- printf("%s: check 2.0\n", FUNC);
+ printf("%s: check 2.0\n", FUNC);
#endif /* QAK */
+ } /* end else */
FUNC_LEAVE (ret_value==FAIL ? ret_value : (num_written >0) ? SUCCEED : FAIL);
} /* H5S_hyper_fscat() */
@@ -1273,6 +1885,258 @@ H5S_hyper_mread (intn dim, H5S_hyper_io_info_t *io_info)
/*-------------------------------------------------------------------------
+ * Function: H5S_hyper_mread_opt
+ *
+ * Purpose: Performs an optimized gather from a memory buffer, based on a
+ * regular hyperslab (i.e. one which was generated from just one call to
+ * H5Sselect_hyperslab).
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, September 12, 2000
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5S_hyper_mread_opt (const void *_buf, size_t elmt_size,
+ const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
+ size_t nelmts, void *_tconv_buf/*out*/)
+{
+ hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Size of the source buffer */
+ hsize_t hsize[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
+ hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */
+ hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset on disk */
+ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary block count */
+ hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block offset */
+ const uint8_t *src=(const uint8_t *)_buf; /* Alias for pointer arithmetic */
+ uint8_t *dst=(uint8_t *)_tconv_buf; /* Alias for pointer arithmetic */
+ intn fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ intn temp_dim; /* Temporary rank holder */
+ intn i; /* Counters */
+ uintn ndims; /* Number of dimensions of dataset */
+ intn actual_read; /* The actual number of elements to read in */
+ size_t num_read=0; /* Number of elements read */
+
+ FUNC_ENTER (H5S_hyper_fread_opt, 0);
+
+#ifdef QAK
+printf("%s: Called!\n",FUNC);
+#endif /* QAK */
+ /* Check if this is the first element read in from the hyperslab */
+ if(mem_iter->hyp.pos[0]==(-1)) {
+ for(i=0; i<mem_space->extent.u.simple.rank; i++)
+ mem_iter->hyp.pos[i]=mem_space->select.sel_info.hslab.diminfo[i].start;
+ } /* end if */
+
+#ifdef QAK
+for(i=0; i<mem_space->extent.u.simple.rank; i++)
+ printf("%s: mem_file->hyp.pos[%d]=%d\n",FUNC,(int)i,(int)mem_iter->hyp.pos[i]);
+#endif /* QAK */
+
+ /* Set the rank of the fastest changing dimension */
+ fast_dim=mem_space->extent.u.simple.rank-1;
+
+ /* Set up the hyperslab and 'zero' arrays */
+ ndims=mem_space->extent.u.simple.rank;
+ /* initialize hyperslab size and offset in memory buffer */
+ for(i=0; i<(int)(ndims+1); i++) {
+ hsize[i]=1; /* hyperslab size is 1, except for last element */
+ zero[i]=0; /* memory offset is 0 */
+ } /* end for */
+ hsize[ndims] = elmt_size;
+
+ /* Set up the size of the memory space */
+ HDmemcpy(mem_size, mem_space->extent.u.simple.size,mem_space->extent.u.simple.rank*sizeof(hsize_t));
+ mem_size[mem_space->extent.u.simple.rank]=elmt_size;
+
+ /* Check if we stopped in the middle of a sequence of elements */
+ if((mem_iter->hyp.pos[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start)%mem_space->select.sel_info.hslab.diminfo[fast_dim].stride!=0) {
+ intn leftover; /* The number of elements left over from the last sequence */
+
+#ifdef QAK
+printf("%s: Check 1.0\n",FUNC);
+#endif /* QAK */
+ /* Calculate the number of elements left in the sequence */
+ leftover=mem_space->select.sel_info.hslab.diminfo[fast_dim].block-((mem_iter->hyp.pos[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start)%mem_space->select.sel_info.hslab.diminfo[fast_dim].stride);
+
+ /* Make certain that we don't read too many */
+ actual_read=MIN(leftover,nelmts);
+
+ /* Set the hyperslab size in the fastest changing dimension to read in */
+ hsize[fast_dim]=actual_read;
+
+ /* Copy the location of the point to get */
+ HDmemcpy(offset, mem_iter->hyp.pos,ndims*sizeof(hssize_t));
+ offset[ndims] = 0;
+
+ /* Add in the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] += mem_space->select.offset[i];
+
+ /* Scatter out the rest of the sequence, if possible */
+ if (H5V_hyper_copy (ndims+1, hsize,
+ hsize, zero, dst,
+ mem_size, offset, src)<0) {
+ HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "unable to gather data from memory");
+ }
+
+ /* Increment the offset of the buffer */
+ dst+=elmt_size*actual_read;
+
+ /* Increment the count read */
+ num_read+=actual_read;
+
+ /* Decrement the number of elements left in selection */
+ mem_iter->hyp.elmt_left-=actual_read;
+
+ /* Advance the point iterator */
+ /* If we had enough buffer space to read in the rest of the sequence
+ * in the fastest changing dimension, move the iterator offset to
+ * the beginning of the next block to read. Otherwise, just advance
+ * the iterator in the fastest changing dimension.
+ */
+ if(actual_read==leftover) {
+ /* Move iterator offset to beginning of next sequence in the fastest changing dimension */
+ H5S_hyper_iter_next(mem_space,mem_iter);
+ } /* end if */
+ else {
+ mem_iter->hyp.pos[fast_dim]+=actual_read; /* whole sequence not read in, just advance fastest dimension offset */
+ } /* end if */
+ } /* end if */
+
+ /* Now that we've cleared the "remainder" of the previous fastest dimension
+ * sequence, we must be at the beginning of a sequence, so use the fancy
+ * algorithm to compute the offsets and run through as many as possible,
+ * until the buffer fills up.
+ */
+ if(num_read<nelmts) { /* Just in case the "remainder" aboce filled the buffer */
+#ifdef QAK
+printf("%s: Check 2.0\n",FUNC);
+#endif /* QAK */
+ /* Compute the arrays to perform I/O on */
+ /* Copy the location of the point to get */
+ HDmemcpy(offset, mem_iter->hyp.pos,ndims*sizeof(hssize_t));
+ offset[ndims] = 0;
+
+ /* Add in the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] += mem_space->select.offset[i];
+
+ /* Compute the current "counts" for this location */
+ for(i=0; i<ndims; i++) {
+ tmp_count[i] = (mem_iter->hyp.pos[i]-mem_space->select.sel_info.hslab.diminfo[i].start)%mem_space->select.sel_info.hslab.diminfo[i].stride;
+ tmp_block[i] = (mem_iter->hyp.pos[i]-mem_space->select.sel_info.hslab.diminfo[i].start)/mem_space->select.sel_info.hslab.diminfo[i].stride;
+ } /* end for */
+
+ /* Set the number of elements to read each time */
+ actual_read=mem_space->select.sel_info.hslab.diminfo[fast_dim].block;
+ hsize[fast_dim]=actual_read;
+#ifdef QAK
+printf("%s: actual_read=%d\n",FUNC,(int)actual_read);
+for(i=0; i<file_space->extent.u.simple.rank; i++)
+ printf("%s: diminfo: start[%d]=%d, stride[%d]=%d, block[%d]=%d, count[%d]=%d\n",FUNC,
+ (int)i,(int)mem_space->select.sel_info.hslab.diminfo[i].start,
+ (int)i,(int)mem_space->select.sel_info.hslab.diminfo[i].stride,
+ (int)i,(int)mem_space->select.sel_info.hslab.diminfo[i].block,
+ (int)i,(int)mem_space->select.sel_info.hslab.diminfo[i].count);
+#endif /* QAK */
+
+ /* Read in data until an entire sequence can't be written out any longer */
+ while(num_read<nelmts) {
+ /* Check if we are running out of room in the buffer */
+ if((actual_read+num_read)>nelmts) {
+ actual_read=nelmts-num_read;
+ hsize[fast_dim]=actual_read;
+ } /* end if */
+
+#ifdef QAK
+printf("%s: num_read=%d\n",FUNC,(int)num_read);
+for(i=0; i<mem_space->extent.u.simple.rank; i++)
+ printf("%s: tmp_count[%d]=%d, offset[%d]=%d\n",FUNC,(int)i,(int)tmp_count[i],(int)i,(int)offset[i]);
+#endif /* QAK */
+
+ /* Scatter out the rest of the sequence, if possible */
+ if (H5V_hyper_copy (ndims+1, hsize,
+ hsize, zero, dst,
+ mem_size, offset, src)<0) {
+ HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "unable to gather data from memory");
+ }
+
+ /* Increment the offset of the buffer */
+ dst+=elmt_size*actual_read;
+
+ /* Increment the count read */
+ num_read+=actual_read;
+
+ /* Decrement the number of elements left in selection */
+ mem_iter->hyp.elmt_left-=actual_read;
+
+ /* Increment the offset and count */
+ temp_dim=fast_dim;
+ while(temp_dim>=0) {
+ if(temp_dim==fast_dim) {
+ /* Move to the next block in the current dimension */
+ /* Check for partial block read! */
+ if(actual_read<mem_space->select.sel_info.hslab.diminfo[fast_dim].block) {
+ offset[temp_dim]+=actual_read;
+ break;
+ } /* end if */
+ else {
+ offset[temp_dim]+=mem_space->select.sel_info.hslab.diminfo[temp_dim].stride; /* reset the offset in the fastest dimension */
+ tmp_count[temp_dim]++;
+ } /* end else */
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<mem_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else {
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ offset[temp_dim]=mem_space->select.sel_info.hslab.diminfo[temp_dim].start+mem_space->select.offset[temp_dim];
+ } /* end else */
+ } /* end if */
+ else {
+ /* Move to the next row in the curent dimension */
+ offset[temp_dim]++;
+ tmp_block[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_block[temp_dim]<mem_space->select.sel_info.hslab.diminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ offset[temp_dim]+=(mem_space->select.sel_info.hslab.diminfo[temp_dim].stride-mem_space->select.sel_info.hslab.diminfo[temp_dim].block);
+ tmp_block[temp_dim]=0;
+ tmp_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<mem_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else {
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ tmp_block[temp_dim]=0;
+ offset[temp_dim]=mem_space->select.sel_info.hslab.diminfo[temp_dim].start+mem_space->select.offset[temp_dim];
+ }
+ } /* end else */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+ } /* end while */
+
+ /* Update the iterator with the location we stopped */
+ HDmemcpy(mem_iter->hyp.pos, offset, ndims*sizeof(hssize_t));
+ } /* end if */
+
+ FUNC_LEAVE (num_read);
+} /* end H5S_hyper_mread_opt() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5S_hyper_mgath
*
* Purpose: Gathers dataset elements from application memory BUF and
@@ -1317,29 +2181,36 @@ H5S_hyper_mgath (const void *_buf, size_t elmt_size,
assert (_buf);
assert (_tconv_buf);
- /* Initialize parameter block for recursive calls */
- io_info.elmt_size=elmt_size;
- io_info.space=mem_space;
- io_info.iter=mem_iter;
- io_info.nelmts=nelmts;
- io_info.src=_buf;
- io_info.dst=_tconv_buf;
-
- /* Set up the size of the memory space */
- HDmemcpy(io_info.mem_size, mem_space->extent.u.simple.size,mem_space->extent.u.simple.rank*sizeof(hsize_t));
- io_info.mem_size[mem_space->extent.u.simple.rank]=elmt_size;
-
- /* Set the hyperslab size to copy */
- io_info.hsize[0]=1;
- H5V_array_fill(io_info.hsize, io_info.hsize, sizeof(io_info.hsize[0]),mem_space->extent.u.simple.rank);
- io_info.hsize[mem_space->extent.u.simple.rank]=elmt_size;
-
- /* Recursively input the hyperslabs currently defined */
- /* starting with the slowest changing dimension */
- num_read=H5S_hyper_mread(-1,&io_info);
+ /* Check for the special case of just one H5Sselect_hyperslab call made */
+ if(mem_space->select.sel_info.hslab.diminfo!=NULL) {
+ /* Use optimized call to read in regular hyperslab */
+ num_read=H5S_hyper_mread_opt(_buf,elmt_size,mem_space,mem_iter,nelmts,_tconv_buf);
+ }
+ else {
+ /* Initialize parameter block for recursive calls */
+ io_info.elmt_size=elmt_size;
+ io_info.space=mem_space;
+ io_info.iter=mem_iter;
+ io_info.nelmts=nelmts;
+ io_info.src=_buf;
+ io_info.dst=_tconv_buf;
+
+ /* Set up the size of the memory space */
+ HDmemcpy(io_info.mem_size, mem_space->extent.u.simple.size,mem_space->extent.u.simple.rank*sizeof(hsize_t));
+ io_info.mem_size[mem_space->extent.u.simple.rank]=elmt_size;
+
+ /* Set the hyperslab size to copy */
+ io_info.hsize[0]=1;
+ H5V_array_fill(io_info.hsize, io_info.hsize, sizeof(io_info.hsize[0]),mem_space->extent.u.simple.rank);
+ io_info.hsize[mem_space->extent.u.simple.rank]=elmt_size;
+
+ /* Recursively input the hyperslabs currently defined */
+ /* starting with the slowest changing dimension */
+ num_read=H5S_hyper_mread(-1,&io_info);
#ifdef QAK
- printf("%s: check 5.0, num_read=%d\n",FUNC,(int)num_read);
+ printf("%s: check 5.0, num_read=%d\n",FUNC,(int)num_read);
#endif /* QAK */
+ } /* end else */
FUNC_LEAVE (num_read);
} /* H5S_hyper_mgath() */
@@ -1488,6 +2359,258 @@ H5S_hyper_mwrite (intn dim, H5S_hyper_io_info_t *io_info)
/*-------------------------------------------------------------------------
+ * Function: H5S_hyper_mwrite_opt
+ *
+ * Purpose: Performs an optimized scatter to a memory buffer, based on a
+ * regular hyperslab (i.e. one which was generated from just one call to
+ * H5Sselect_hyperslab).
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, September 12, 2000
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5S_hyper_mwrite_opt (const void *_tconv_buf, size_t elmt_size,
+ const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
+ size_t nelmts, void *_buf/*out*/)
+{
+ hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Size of the source buffer */
+ hsize_t hsize[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
+ hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */
+ hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset on disk */
+ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary block count */
+ hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block offset */
+ const uint8_t *src=(const uint8_t *)_tconv_buf; /* Alias for pointer arithmetic */
+ uint8_t *dst=(uint8_t *)_buf; /* Alias for pointer arithmetic */
+ intn fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ intn temp_dim; /* Temporary rank holder */
+ intn i; /* Counters */
+ uintn ndims; /* Number of dimensions of dataset */
+ intn actual_write; /* The actual number of elements to read in */
+ size_t num_write=0; /* Number of elements read */
+
+ FUNC_ENTER (H5S_hyper_fwrite_opt, 0);
+
+#ifdef QAK
+printf("%s: Called!\n",FUNC);
+#endif /* QAK */
+ /* Check if this is the first element read in from the hyperslab */
+ if(mem_iter->hyp.pos[0]==(-1)) {
+ for(i=0; i<mem_space->extent.u.simple.rank; i++)
+ mem_iter->hyp.pos[i]=mem_space->select.sel_info.hslab.diminfo[i].start;
+ } /* end if */
+
+#ifdef QAK
+for(i=0; i<mem_space->extent.u.simple.rank; i++)
+ printf("%s: mem_file->hyp.pos[%d]=%d\n",FUNC,(int)i,(int)mem_iter->hyp.pos[i]);
+#endif /* QAK */
+
+ /* Set the rank of the fastest changing dimension */
+ fast_dim=mem_space->extent.u.simple.rank-1;
+
+ /* Set up the hyperslab and 'zero' arrays */
+ ndims=mem_space->extent.u.simple.rank;
+ /* initialize hyperslab size and offset in memory buffer */
+ for(i=0; i<(int)(ndims+1); i++) {
+ hsize[i]=1; /* hyperslab size is 1, except for last element */
+ zero[i]=0; /* memory offset is 0 */
+ } /* end for */
+ hsize[ndims] = elmt_size;
+
+ /* Set up the size of the memory space */
+ HDmemcpy(mem_size, mem_space->extent.u.simple.size,mem_space->extent.u.simple.rank*sizeof(hsize_t));
+ mem_size[mem_space->extent.u.simple.rank]=elmt_size;
+
+ /* Check if we stopped in the middle of a sequence of elements */
+ if((mem_iter->hyp.pos[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start)%mem_space->select.sel_info.hslab.diminfo[fast_dim].stride!=0) {
+ intn leftover; /* The number of elements left over from the last sequence */
+
+#ifdef QAK
+printf("%s: Check 1.0\n",FUNC);
+#endif /* QAK */
+ /* Calculate the number of elements left in the sequence */
+ leftover=mem_space->select.sel_info.hslab.diminfo[fast_dim].block-((mem_iter->hyp.pos[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start)%mem_space->select.sel_info.hslab.diminfo[fast_dim].stride);
+
+ /* Make certain that we don't write too many */
+ actual_write=MIN(leftover,nelmts);
+
+ /* Set the hyperslab size in the fastest changing dimension to write in */
+ hsize[fast_dim]=actual_write;
+
+ /* Copy the location of the point to get */
+ HDmemcpy(offset, mem_iter->hyp.pos,ndims*sizeof(hssize_t));
+ offset[ndims] = 0;
+
+ /* Add in the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] += mem_space->select.offset[i];
+
+ /* Scatter out the rest of the sequence, if possible */
+ if (H5V_hyper_copy (ndims+1, hsize,
+ mem_size, offset, dst,
+ hsize, zero, src)<0) {
+ HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "unable to gather data from memory");
+ }
+
+ /* Increment the offset of the buffer */
+ src+=elmt_size*actual_write;
+
+ /* Increment the count write */
+ num_write+=actual_write;
+
+ /* Decrement the number of elements left in selection */
+ mem_iter->hyp.elmt_left-=actual_write;
+
+ /* Advance the point iterator */
+ /* If we had enough buffer space to write out the rest of the sequence
+ * in the fastest changing dimension, move the iterator offset to
+ * the beginning of the next block to write. Otherwise, just advance
+ * the iterator in the fastest changing dimension.
+ */
+ if(actual_write==leftover) {
+ /* Move iterator offset to beginning of next sequence in the fastest changing dimension */
+ H5S_hyper_iter_next(mem_space,mem_iter);
+ } /* end if */
+ else {
+ mem_iter->hyp.pos[fast_dim]+=actual_write; /* whole sequence not written out, just advance fastest dimension offset */
+ } /* end if */
+ } /* end if */
+
+ /* Now that we've cleared the "remainder" of the previous fastest dimension
+ * sequence, we must be at the beginning of a sequence, so use the fancy
+ * algorithm to compute the offsets and run through as many as possible,
+ * until the buffer fills up.
+ */
+ if(num_write<nelmts) { /* Just in case the "remainder" aboce filled the buffer */
+#ifdef QAK
+printf("%s: Check 2.0\n",FUNC);
+#endif /* QAK */
+ /* Compute the arrays to perform I/O on */
+ /* Copy the location of the point to get */
+ HDmemcpy(offset, mem_iter->hyp.pos,ndims*sizeof(hssize_t));
+ offset[ndims] = 0;
+
+ /* Add in the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] += mem_space->select.offset[i];
+
+ /* Compute the current "counts" for this location */
+ for(i=0; i<ndims; i++) {
+ tmp_count[i] = (mem_iter->hyp.pos[i]-mem_space->select.sel_info.hslab.diminfo[i].start)%mem_space->select.sel_info.hslab.diminfo[i].stride;
+ tmp_block[i] = (mem_iter->hyp.pos[i]-mem_space->select.sel_info.hslab.diminfo[i].start)/mem_space->select.sel_info.hslab.diminfo[i].stride;
+ } /* end for */
+
+ /* Set the number of elements to write each time */
+ actual_write=mem_space->select.sel_info.hslab.diminfo[fast_dim].block;
+ hsize[fast_dim]=actual_write;
+#ifdef QAK
+printf("%s: actual_write=%d\n",FUNC,(int)actual_write);
+for(i=0; i<file_space->extent.u.simple.rank; i++)
+ printf("%s: diminfo: start[%d]=%d, stride[%d]=%d, block[%d]=%d, count[%d]=%d\n",FUNC,
+ (int)i,(int)mem_space->select.sel_info.hslab.diminfo[i].start,
+ (int)i,(int)mem_space->select.sel_info.hslab.diminfo[i].stride,
+ (int)i,(int)mem_space->select.sel_info.hslab.diminfo[i].block,
+ (int)i,(int)mem_space->select.sel_info.hslab.diminfo[i].count);
+#endif /* QAK */
+
+ /* Read in data until an entire sequence can't be written out any longer */
+ while(num_write<nelmts) {
+ /* Check if we are running out of room in the buffer */
+ if((actual_write+num_write)>nelmts) {
+ actual_write=nelmts-num_write;
+ hsize[fast_dim]=actual_write;
+ } /* end if */
+
+#ifdef QAK
+printf("%s: num_write=%d\n",FUNC,(int)num_write);
+for(i=0; i<mem_space->extent.u.simple.rank; i++)
+ printf("%s: tmp_count[%d]=%d, offset[%d]=%d\n",FUNC,(int)i,(int)tmp_count[i],(int)i,(int)offset[i]);
+#endif /* QAK */
+
+ /* Scatter out the rest of the sequence, if possible */
+ if (H5V_hyper_copy (ndims+1, hsize,
+ mem_size, offset, dst,
+ hsize, zero, src)<0) {
+ HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "unable to gather data from memory");
+ }
+
+ /* Increment the offset of the buffer */
+ src+=elmt_size*actual_write;
+
+ /* Increment the count write */
+ num_write+=actual_write;
+
+ /* Decrement the number of elements left in selection */
+ mem_iter->hyp.elmt_left-=actual_write;
+
+ /* Increment the offset and count */
+ temp_dim=fast_dim;
+ while(temp_dim>=0) {
+ if(temp_dim==fast_dim) {
+ /* Move to the next block in the current dimension */
+ /* Check for partial block write! */
+ if(actual_write<mem_space->select.sel_info.hslab.diminfo[fast_dim].block) {
+ offset[temp_dim]+=actual_write;
+ break;
+ } /* end if */
+ else {
+ offset[temp_dim]+=mem_space->select.sel_info.hslab.diminfo[temp_dim].stride; /* reset the offset in the fastest dimension */
+ tmp_count[temp_dim]++;
+ } /* end else */
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<mem_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else {
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ offset[temp_dim]=mem_space->select.sel_info.hslab.diminfo[temp_dim].start+mem_space->select.offset[temp_dim];
+ } /* end else */
+ } /* end if */
+ else {
+ /* Move to the next row in the curent dimension */
+ offset[temp_dim]++;
+ tmp_block[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_block[temp_dim]<mem_space->select.sel_info.hslab.diminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ offset[temp_dim]+=(mem_space->select.sel_info.hslab.diminfo[temp_dim].stride-mem_space->select.sel_info.hslab.diminfo[temp_dim].block);
+ tmp_block[temp_dim]=0;
+ tmp_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<mem_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ break;
+ else {
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ tmp_block[temp_dim]=0;
+ offset[temp_dim]=mem_space->select.sel_info.hslab.diminfo[temp_dim].start+mem_space->select.offset[temp_dim];
+ }
+ } /* end else */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+ } /* end while */
+
+ /* Update the iterator with the location we stopped */
+ HDmemcpy(mem_iter->hyp.pos, offset, ndims*sizeof(hssize_t));
+ } /* end if */
+
+ FUNC_LEAVE (num_write);
+} /* end H5S_hyper_mwrite_opt() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5S_hyper_mscat
*
* Purpose: Scatters NELMTS data points from the type conversion buffer
@@ -1509,8 +2632,8 @@ H5S_hyper_mscat (const void *_tconv_buf, size_t elmt_size,
const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
size_t nelmts, void *_buf/*out*/)
{
- H5S_hyper_io_info_t io_info; /* Block of parameters to pass into recursive calls */
- size_t num_read; /* number of elements read into buffer */
+ H5S_hyper_io_info_t io_info; /* Block of parameters to pass into recursive calls */
+ size_t num_written; /* number of elements written into buffer */
FUNC_ENTER (H5S_hyper_mscat, 0);
@@ -1522,34 +2645,41 @@ H5S_hyper_mscat (const void *_tconv_buf, size_t elmt_size,
assert (_buf);
assert (_tconv_buf);
- /* Initialize parameter block for recursive calls */
- io_info.elmt_size=elmt_size;
- io_info.space=mem_space;
- io_info.iter=mem_iter;
- io_info.nelmts=nelmts;
- io_info.src=_tconv_buf;
- io_info.dst=_buf;
-
- /* Set up the size of the memory space */
- HDmemcpy(io_info.mem_size, mem_space->extent.u.simple.size,mem_space->extent.u.simple.rank*sizeof(hsize_t));
- io_info.mem_size[mem_space->extent.u.simple.rank]=elmt_size;
-
- /* Set the hyperslab size to copy */
- io_info.hsize[0]=1;
- H5V_array_fill(io_info.hsize, io_info.hsize, sizeof(io_info.hsize[0]), mem_space->extent.u.simple.rank);
- io_info.hsize[mem_space->extent.u.simple.rank]=elmt_size;
-
- /* Recursively input the hyperslabs currently defined */
- /* starting with the slowest changing dimension */
+ /* Check for the special case of just one H5Sselect_hyperslab call made */
+ if(mem_space->select.sel_info.hslab.diminfo!=NULL) {
+ /* Use optimized call to write out regular hyperslab */
+ num_written=H5S_hyper_mwrite_opt(_tconv_buf,elmt_size,mem_space,mem_iter,nelmts,_buf);
+ }
+ else {
+ /* Initialize parameter block for recursive calls */
+ io_info.elmt_size=elmt_size;
+ io_info.space=mem_space;
+ io_info.iter=mem_iter;
+ io_info.nelmts=nelmts;
+ io_info.src=_tconv_buf;
+ io_info.dst=_buf;
+
+ /* Set up the size of the memory space */
+ HDmemcpy(io_info.mem_size, mem_space->extent.u.simple.size,mem_space->extent.u.simple.rank*sizeof(hsize_t));
+ io_info.mem_size[mem_space->extent.u.simple.rank]=elmt_size;
+
+ /* Set the hyperslab size to copy */
+ io_info.hsize[0]=1;
+ H5V_array_fill(io_info.hsize, io_info.hsize, sizeof(io_info.hsize[0]), mem_space->extent.u.simple.rank);
+ io_info.hsize[mem_space->extent.u.simple.rank]=elmt_size;
+
+ /* Recursively input the hyperslabs currently defined */
+ /* starting with the slowest changing dimension */
#ifdef QAK
- printf("%s: check 1.0\n",FUNC);
+ printf("%s: check 1.0\n",FUNC);
#endif /* QAK */
- num_read=H5S_hyper_mwrite(-1,&io_info);
+ num_written=H5S_hyper_mwrite(-1,&io_info);
#ifdef QAK
- printf("%s: check 2.0\n",FUNC);
+ printf("%s: check 2.0\n",FUNC);
#endif /* QAK */
+ } /* end else */
- FUNC_LEAVE (num_read>0 ? SUCCEED : FAIL);
+ FUNC_LEAVE (num_written>0 ? SUCCEED : FAIL);
} /* H5S_hyper_mscat() */
@@ -2380,30 +3510,36 @@ H5S_hyper_release (H5S_t *space)
/* Reset the number of points selected */
space->select.num_elem=0;
- /* Release the per-dimension selection info */
- if(space->select.sel_info.hslab.diminfo!=NULL)
+ /* Release the regular selection info */
+ if(space->select.sel_info.hslab.diminfo!=NULL) {
H5FL_ARR_FREE(H5S_hyper_dim_t,space->select.sel_info.hslab.diminfo);
- space->select.sel_info.hslab.diminfo = NULL;
+ space->select.sel_info.hslab.diminfo = NULL;
+ } /* end if */
- /* Release hi and lo boundary information */
- for(i=0; i<space->extent.u.simple.rank; i++) {
- H5FL_ARR_FREE(H5S_hyper_bound_t,space->select.sel_info.hslab.hyper_lst->lo_bounds[i]);
- space->select.sel_info.hslab.hyper_lst->lo_bounds[i] = NULL;
- } /* end for */
- H5FL_ARR_FREE(H5S_hyper_bound_ptr_t,space->select.sel_info.hslab.hyper_lst->lo_bounds);
- space->select.sel_info.hslab.hyper_lst->lo_bounds = NULL;
+ /* Release irregular hyperslab information */
+ if(space->select.sel_info.hslab.hyper_lst!=NULL) {
+ /* Release hi and lo boundary information */
+ if(space->select.sel_info.hslab.hyper_lst->lo_bounds!=NULL) {
+ for(i=0; i<space->extent.u.simple.rank; i++) {
+ H5FL_ARR_FREE(H5S_hyper_bound_t,space->select.sel_info.hslab.hyper_lst->lo_bounds[i]);
+ space->select.sel_info.hslab.hyper_lst->lo_bounds[i] = NULL;
+ } /* end for */
+ H5FL_ARR_FREE(H5S_hyper_bound_ptr_t,space->select.sel_info.hslab.hyper_lst->lo_bounds);
+ space->select.sel_info.hslab.hyper_lst->lo_bounds = NULL;
+ } /* end if */
- /* Release list of selected regions */
- curr=space->select.sel_info.hslab.hyper_lst->head;
- while(curr!=NULL) {
- next=curr->next;
- H5S_hyper_node_release(curr);
- curr=next;
- } /* end while */
+ /* Release list of selected regions */
+ curr=space->select.sel_info.hslab.hyper_lst->head;
+ while(curr!=NULL) {
+ next=curr->next;
+ H5S_hyper_node_release(curr);
+ curr=next;
+ } /* end while */
- /* Release hyperslab selection node itself */
- H5FL_FREE(H5S_hyper_list_t,space->select.sel_info.hslab.hyper_lst);
- space->select.sel_info.hslab.hyper_lst=NULL;
+ /* Release hyperslab selection node itself */
+ H5FL_FREE(H5S_hyper_list_t,space->select.sel_info.hslab.hyper_lst);
+ space->select.sel_info.hslab.hyper_lst=NULL;
+ } /* end if */
#ifdef QAK
printf("%s: check 2.0\n",FUNC);
@@ -2522,7 +3658,7 @@ H5S_hyper_compare_bounds (const void *r1, const void *r2)
herr_t
H5S_hyper_copy (H5S_t *dst, const H5S_t *src)
{
- H5S_hyper_list_t *new_hyper; /* New hyperslab selection */
+ H5S_hyper_list_t *new_hyper=NULL; /* New hyperslab selection */
H5S_hyper_node_t *curr, *new, *new_head; /* Hyperslab information nodes */
H5S_hyper_dim_t *new_diminfo=NULL; /* New per-dimension info array[rank] */
intn i; /* Counters */
@@ -2537,6 +3673,7 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src)
#ifdef QAK
printf("%s: check 3.0\n", FUNC);
#endif /* QAK */
+ /* Check if there is regular hyperslab information to copy */
if(src->select.sel_info.hslab.diminfo!=NULL) {
/* Create the per-dimension selection info */
if((new_diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,src->extent.u.simple.rank,0))==NULL)
@@ -2552,87 +3689,91 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src)
} /* end if */
dst->select.sel_info.hslab.diminfo = new_diminfo;
- /* Create the new hyperslab information node */
- if((new_hyper = H5FL_ALLOC(H5S_hyper_list_t,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
- "can't allocate point node");
+ /* Check if there is irregular hyperslab information to copy */
+ if(src->select.sel_info.hslab.hyper_lst!=NULL) {
+ /* Create the new hyperslab information node */
+ if((new_hyper = H5FL_ALLOC(H5S_hyper_list_t,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "can't allocate point node");
- /* Copy the basic hyperslab selection information */
- *new_hyper=*(src->select.sel_info.hslab.hyper_lst);
+ /* Copy the basic hyperslab selection information */
+ *new_hyper=*(src->select.sel_info.hslab.hyper_lst);
- /* Attach the hyperslab information to the destination dataspace */
- dst->select.sel_info.hslab.hyper_lst=new_hyper;
-
#ifdef QAK
- printf("%s: check 4.0\n", FUNC);
+ printf("%s: check 4.0\n", FUNC);
#endif /* QAK */
- /* Allocate space for the low & high bound arrays */
- if((new_hyper->lo_bounds = H5FL_ARR_ALLOC(H5S_hyper_bound_ptr_t,src->extent.u.simple.rank,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
- "can't allocate boundary node");
- for(i=0; i<src->extent.u.simple.rank; i++) {
- if((new_hyper->lo_bounds[i] = H5FL_ARR_ALLOC(H5S_hyper_bound_t,src->select.sel_info.hslab.hyper_lst->count,0))==NULL)
+ /* Allocate space for the low & high bound arrays */
+ if((new_hyper->lo_bounds = H5FL_ARR_ALLOC(H5S_hyper_bound_ptr_t,src->extent.u.simple.rank,0))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
- "can't allocate boundary list");
- } /* end for */
+ "can't allocate boundary node");
+ for(i=0; i<src->extent.u.simple.rank; i++) {
+ if((new_hyper->lo_bounds[i] = H5FL_ARR_ALLOC(H5S_hyper_bound_t,src->select.sel_info.hslab.hyper_lst->count,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "can't allocate boundary list");
+ } /* end for */
#ifdef QAK
- printf("%s: check 5.0\n", FUNC);
+ printf("%s: check 5.0\n", FUNC);
#endif /* QAK */
- /* Copy the hyperslab selection nodes, adding them to the lo & hi bound arrays also */
- curr=src->select.sel_info.hslab.hyper_lst->head;
- new_head=NULL;
- u=0;
- while(curr!=NULL) {
+ /* Copy the hyperslab selection nodes, adding them to the lo & hi bound arrays also */
+ curr=src->select.sel_info.hslab.hyper_lst->head;
+ new_head=NULL;
+ u=0;
+ while(curr!=NULL) {
#ifdef QAK
- printf("%s: check 5.1\n", FUNC);
+ printf("%s: check 5.1\n", FUNC);
#endif /* QAK */
- /* Create each point */
- if((new = H5FL_ALLOC(H5S_hyper_node_t,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
- "can't allocate point node");
- HDmemcpy(new,curr,sizeof(H5S_hyper_node_t)); /* copy caching information */
- if((new->start = H5FL_ARR_ALLOC(hsize_t,src->extent.u.simple.rank,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
- "can't allocate coordinate information");
- if((new->end = H5FL_ARR_ALLOC(hsize_t,src->extent.u.simple.rank,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
- "can't allocate coordinate information");
- HDmemcpy(new->start,curr->start,(src->extent.u.simple.rank*sizeof(hssize_t)));
- HDmemcpy(new->end,curr->end,(src->extent.u.simple.rank*sizeof(hssize_t)));
- new->next=NULL;
-
- /* Insert into low & high bound arrays */
- for(i=0; i<src->extent.u.simple.rank; i++) {
- new_hyper->lo_bounds[i][u].bound=new->start[i];
- new_hyper->lo_bounds[i][u].node=new;
- } /* end for */
- u++; /* Increment the location of the next node in the boundary arrays */
+ /* Create each point */
+ if((new = H5FL_ALLOC(H5S_hyper_node_t,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "can't allocate point node");
+ HDmemcpy(new,curr,sizeof(H5S_hyper_node_t)); /* copy caching information */
+ if((new->start = H5FL_ARR_ALLOC(hsize_t,src->extent.u.simple.rank,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "can't allocate coordinate information");
+ if((new->end = H5FL_ARR_ALLOC(hsize_t,src->extent.u.simple.rank,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "can't allocate coordinate information");
+ HDmemcpy(new->start,curr->start,(src->extent.u.simple.rank*sizeof(hssize_t)));
+ HDmemcpy(new->end,curr->end,(src->extent.u.simple.rank*sizeof(hssize_t)));
+ new->next=NULL;
+
+ /* Insert into low & high bound arrays */
+ for(i=0; i<src->extent.u.simple.rank; i++) {
+ new_hyper->lo_bounds[i][u].bound=new->start[i];
+ new_hyper->lo_bounds[i][u].node=new;
+ } /* end for */
+ u++; /* Increment the location of the next node in the boundary arrays */
- /* Keep the order the same when copying */
- if(new_head==NULL)
- new_head=new_hyper->head=new;
- else {
- new_head->next=new;
- new_head=new;
- } /* end else */
+ /* Keep the order the same when copying */
+ if(new_head==NULL)
+ new_head=new_hyper->head=new;
+ else {
+ new_head->next=new;
+ new_head=new;
+ } /* end else */
- curr=curr->next;
- } /* end while */
+ curr=curr->next;
+ } /* end while */
#ifdef QAK
- printf("%s: check 6.0\n", FUNC);
+ printf("%s: check 6.0\n", FUNC);
#endif /* QAK */
- /* Sort the boundary array */
- for(i=0; i<src->extent.u.simple.rank; i++)
- HDqsort(new_hyper->lo_bounds[i], new_hyper->count, sizeof(H5S_hyper_bound_t), H5S_hyper_compare_bounds);
+ /* Sort the boundary array */
+ for(i=0; i<src->extent.u.simple.rank; i++)
+ HDqsort(new_hyper->lo_bounds[i], new_hyper->count, sizeof(H5S_hyper_bound_t), H5S_hyper_compare_bounds);
#ifdef QAK
- printf("%s: check 7.0\n", FUNC);
+ printf("%s: check 7.0\n", FUNC);
#endif /* QAK */
+ } /* end if */
+
+ /* Attach the hyperslab information to the destination dataspace */
+ dst->select.sel_info.hslab.hyper_lst=new_hyper;
done:
FUNC_LEAVE (ret_value);
} /* end H5S_hyper_copy() */
+
/*--------------------------------------------------------------------------
NAME
@@ -2665,23 +3806,49 @@ H5S_hyper_select_valid (const H5S_t *space)
assert(space);
- /* Check each point to determine whether selection+offset is within extent */
- curr=space->select.sel_info.hslab.hyper_lst->head;
- while(curr!=NULL && ret_value==TRUE) {
+ /* Check for a "regular" hyperslab selection */
+ if(space->select.sel_info.hslab.diminfo != NULL) {
+ const H5S_hyper_dim_t *diminfo=space->select.sel_info.hslab.diminfo; /* local alias for diminfo */
+ hssize_t end; /* The high bound of a region in a dimension */
+
/* Check each dimension */
for(i=0; i<space->extent.u.simple.rank; i++) {
- /* Check if an offset has been defined */
- /* Bounds check the selected point + offset against the extent */
- if(((curr->start[i]+space->select.offset[i])>(hssize_t)space->extent.u.simple.size[i])
- || ((curr->start[i]+space->select.offset[i])<0)
- || ((curr->end[i]+space->select.offset[i])>(hssize_t)space->extent.u.simple.size[i])
- || ((curr->end[i]+space->select.offset[i])<0)) {
+ /* Bounds check the start point in this dimension */
+ if((diminfo[i].start+space->select.offset[i])<0 ||
+ (diminfo[i].start+space->select.offset[i])>=(hssize_t)space->extent.u.simple.size[i]) {
+ ret_value=FALSE;
+ break;
+ } /* end if */
+
+ /* Compute the largest location in this dimension */
+ end=diminfo[i].start+diminfo[i].stride*(diminfo[i].count-1)+(diminfo[i].block-1)+space->select.offset[i];
+
+ /* Bounds check the end point in this dimension */
+ if(end<0 || end>=(hssize_t)space->extent.u.simple.size[i]) {
ret_value=FALSE;
break;
} /* end if */
} /* end for */
+ } /* end if */
+ else {
+ /* Check each point to determine whether selection+offset is within extent */
+ curr=space->select.sel_info.hslab.hyper_lst->head;
+ while(curr!=NULL && ret_value==TRUE) {
+ /* Check each dimension */
+ for(i=0; i<space->extent.u.simple.rank; i++) {
+ /* Check if an offset has been defined */
+ /* Bounds check the selected point + offset against the extent */
+ if(((curr->start[i]+space->select.offset[i])>(hssize_t)space->extent.u.simple.size[i])
+ || ((curr->start[i]+space->select.offset[i])<0)
+ || ((curr->end[i]+space->select.offset[i])>(hssize_t)space->extent.u.simple.size[i])
+ || ((curr->end[i]+space->select.offset[i])<0)) {
+ ret_value=FALSE;
+ break;
+ } /* end if */
+ } /* end for */
- curr=curr->next;
+ curr=curr->next;
+ } /* end while */
} /* end while */
FUNC_LEAVE (ret_value);
@@ -2973,55 +4140,71 @@ H5S_hyper_select_contiguous(const H5S_t *space)
assert(space);
- /* If there is more than one hyperslab in the selection, they are not contiguous */
- if(space->select.sel_info.hslab.hyper_lst->count>1)
- ret_value=FALSE;
- else { /* If there is one hyperslab, then it might be contiguous */
- /* Get the dataspace extent rank */
- rank=space->extent.u.simple.rank;
-
- /* Get the hyperslab node */
- node=space->select.sel_info.hslab.hyper_lst->head;
-
- /*
- * For a hyperslab to be contiguous, it's size must be the same as the
- * dataspace extent's in all but the slowest changing dimension
- */
- ret_value=TRUE; /* assume true and reset if the dimensions don't match */
- for(i=1; i<rank; i++) {
- if(((node->end[i]-node->start[i])+1)!=(hssize_t)space->extent.u.simple.size[i]) {
- ret_value=FALSE;
- break;
- } /* end if */
- }
+ /* Check for a "regular" hyperslab selection */
+ if(space->select.sel_info.hslab.diminfo != NULL) {
+ /*
+ * For a regular hyperslab to be contiguous, it must have only one
+ * block (i.e. count==1 in all dimensions) and the block size must be
+ * the same as the dataspace extent's in all but the slowest changing
+ * dimension.
+ */
+ ret_value=TRUE; /* assume true and reset if the dimensions don't match */
+ for(i=1; i<space->extent.u.simple.rank; i++) {
+ if(space->select.sel_info.hslab.diminfo[i].block>1 || space->select.sel_info.hslab.diminfo[i].block!=(hssize_t)space->extent.u.simple.size[i]) {
+ ret_value=FALSE;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+ else {
+ /* If there is more than one hyperslab in the selection, they are not contiguous */
+ if(space->select.sel_info.hslab.hyper_lst->count>1)
+ ret_value=FALSE;
+ else { /* If there is one hyperslab, then it might be contiguous */
+ /* Get the dataspace extent rank */
+ rank=space->extent.u.simple.rank;
+
+ /* Get the hyperslab node */
+ node=space->select.sel_info.hslab.hyper_lst->head;
+
+ /*
+ * For a hyperslab to be contiguous, it's size must be the same as the
+ * dataspace extent's in all but the slowest changing dimension
+ */
+ ret_value=TRUE; /* assume true and reset if the dimensions don't match */
+ for(i=1; i<rank; i++) {
+ if(((node->end[i]-node->start[i])+1)!=(hssize_t)space->extent.u.simple.size[i]) {
+ ret_value=FALSE;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end else */
} /* end else */
FUNC_LEAVE (ret_value);
} /* H5S_hyper_select_contiguous() */
/*-------------------------------------------------------------------------
- * Function: H5S_select_hyperslab
+ * Function: H5S_generate_hyperlab
*
- * Purpose: Internal version of H5Sselect_hyperslab().
+ * Purpose: Generate hyperslab information from H5S_select_hyperslab()
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke (split from HSselect_hyperslab()).
- * Tuesday, August 25, 1998
+ * Programmer: Quincey Koziol (split from HS_select_hyperslab()).
+ * Tuesday, September 12, 2000
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
+static herr_t
+H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op,
const hssize_t start[/*space_id*/],
const hsize_t stride[/*space_id*/],
const hsize_t count[/*space_id*/],
const hsize_t block[/*space_id*/])
{
- hsize_t *_stride=NULL; /* Stride array */
- hsize_t *_block=NULL; /* Block size array */
hssize_t slab[H5O_LAYOUT_NDIMS]; /* Location of the block to add for strided selections */
size_t slice[H5O_LAYOUT_NDIMS]; /* Size of preceding dimension's slice */
H5S_hyper_node_t *add=NULL, /* List of hyperslab nodes to add */
@@ -3030,54 +4213,18 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
uintn acc; /* Accumulator for building slices */
uintn contig; /* whether selection is contiguous or not */
int i,j; /* Counters */
- H5S_hyper_dim_t *diminfo; /* per-dimension info for the selection */
herr_t ret_value=FAIL; /* return value */
- FUNC_ENTER (H5S_select_hyperslab, FAIL);
+ FUNC_ENTER (H5S_generate_hyperslab, FAIL);
/* Check args */
+ assert(block);
+ assert(stride);
assert(space);
assert(start);
assert(count);
assert(op>H5S_SELECT_NOOP && op<H5S_SELECT_INVALID);
- /* Fill in the correct stride values */
- if(stride==NULL) {
- hssize_t fill=1;
-
- /* Allocate temporary buffer */
- if ((_stride=H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,
- "memory allocation failed for stride buffer");
- H5V_array_fill(_stride,&fill,sizeof(hssize_t),space->extent.u.simple.rank);
- stride = _stride;
- }
-
- /* Fill in the correct block values */
- if(block==NULL) {
- hssize_t fill=1;
-
- /* Allocate temporary buffer */
- if ((_block=H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,
- "memory allocation failed for stride buffer");
- H5V_array_fill(_block,&fill,sizeof(hssize_t),space->extent.u.simple.rank);
- block = _block;
- }
-
- /*
- * Check for overlapping hyperslab blocks in new selection (remove when
- * real block-merging algorithm is in place? -QAK).
- */
- if(op==H5S_SELECT_SET && block!=NULL) {
- for(i=0; i<space->extent.u.simple.rank; i++) {
- if(stride[i]<block[i]) {
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
- "hyperslab blocks overlap");
- } /* end if */
- } /* end for */
- } /* end if */
-
/* Determine if selection is contiguous */
/* assume hyperslab is contiguous, until proven otherwise */
contig=1;
@@ -3092,13 +4239,6 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
#ifdef QAK
printf("%s: check 1.0, contig=%d, op=%s\n",FUNC,(int)contig,(op==H5S_SELECT_SET? "H5S_SELECT_SET" : (op==H5S_SELECT_OR ? "H5S_SELECT_OR" : "Unknown")));
#endif /* QAK */
- /* If we are setting a new selection, remove current selection first */
- if(op==H5S_SELECT_SET) {
- if(H5S_select_release(space)<0) {
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL,
- "can't release hyperslab");
- } /* end if */
- } /* end if */
#ifdef QAK
printf("%s: check 2.0, rank=%d\n",FUNC,(int)space->extent.u.simple.rank);
@@ -3176,22 +4316,6 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
H5S_hyper_clip(space,add,&uniq,NULL);
add=uniq;
} /* end if */
- else {
-#ifdef QAK
- printf("%s: check 4.5.2\n",FUNC);
-#endif /* QAK */
- /* Copy all the per-dimension selection info into the space descriptor */
- if((diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank,0))==NULL) {
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector");
- } /* end if */
- for(i=0; i<space->extent.u.simple.rank; i++) {
- diminfo[i].start = start[i];
- diminfo[i].stride = stride[i];
- diminfo[i].count = count[i];
- diminfo[i].block = block[i];
- } /* end for */
- space->select.sel_info.hslab.diminfo = diminfo;
- } /* end else */
#ifdef QAK
printf("%s: check 4.5.5\n",FUNC);
#endif /* QAK */
@@ -3215,8 +4339,186 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
printf("%s: check 6.0\n",FUNC);
#endif /* QAK */
+ /* Set return value */
+ ret_value=SUCCEED;
+
+done:
+ FUNC_LEAVE (ret_value);
+} /* end H5S_generate_hyperslab() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_select_hyperslab
+ *
+ * Purpose: Internal version of H5Sselect_hyperslab().
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke (split from HSselect_hyperslab()).
+ * Tuesday, August 25, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
+ const hssize_t start[/*space_id*/],
+ const hsize_t stride[/*space_id*/],
+ const hsize_t count[/*space_id*/],
+ const hsize_t block[/*space_id*/])
+{
+ hsize_t *_stride=NULL; /* Stride array */
+ hsize_t *_block=NULL; /* Block size array */
+ hssize_t slab[H5O_LAYOUT_NDIMS]; /* Location of the block to add for strided selections */
+ size_t slice[H5O_LAYOUT_NDIMS]; /* Size of preceding dimension's slice */
+ H5S_hyper_node_t *add=NULL, /* List of hyperslab nodes to add */
+ *uniq=NULL, /* List of unique hyperslab nodes */
+ *tmp; /* Temporary hyperslab node */
+ uintn acc; /* Accumulator for building slices */
+ uintn contig; /* whether selection is contiguous or not */
+ int i,j; /* Counters */
+ H5S_hyper_dim_t *diminfo; /* per-dimension info for the selection */
+ herr_t ret_value=FAIL; /* return value */
+
+ FUNC_ENTER (H5S_select_hyperslab, FAIL);
+
+ /* Check args */
+ assert(space);
+ assert(start);
+ assert(count);
+ assert(op>H5S_SELECT_NOOP && op<H5S_SELECT_INVALID);
+
+ /* Fill in the correct stride values */
+ if(stride==NULL) {
+ hssize_t fill=1;
+
+ /* Allocate temporary buffer */
+ if ((_stride=H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0))==NULL)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "memory allocation failed for stride buffer");
+ H5V_array_fill(_stride,&fill,sizeof(hssize_t),space->extent.u.simple.rank);
+ stride = _stride;
+ }
+
+ /* Fill in the correct block values */
+ if(block==NULL) {
+ hssize_t fill=1;
+
+ /* Allocate temporary buffer */
+ if ((_block=H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0))==NULL)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "memory allocation failed for stride buffer");
+ H5V_array_fill(_block,&fill,sizeof(hssize_t),space->extent.u.simple.rank);
+ block = _block;
+ }
+
+ /* Determine if selection is contiguous */
+ /* assume hyperslab is contiguous, until proven otherwise */
+ contig=1;
+ for(i=0; i<space->extent.u.simple.rank; i++) {
+ /* contiguous hyperslabs have the block size equal to the stride */
+ if(stride[i]!=block[i]) {
+ contig=0; /* hyperslab isn't contiguous */
+ break; /* no use looking further */
+ } /* end if */
+ } /* end for */
+
+#ifdef QAK
+ printf("%s: check 1.0, contig=%d, op=%s\n",FUNC,(int)contig,(op==H5S_SELECT_SET? "H5S_SELECT_SET" : (op==H5S_SELECT_OR ? "H5S_SELECT_OR" : "Unknown")));
+#endif /* QAK */
+ if(op==H5S_SELECT_SET) {
+ /*
+ * Check for overlapping hyperslab blocks in new selection
+ * (remove when real block-merging algorithm is in place? -QAK).
+ */
+ for(i=0; i<space->extent.u.simple.rank; i++) {
+ if(count[i]>1 && stride[i]<block[i]) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "hyperslab blocks overlap");
+ } /* end if */
+ } /* end for */
+
+ /* If we are setting a new selection, remove current selection first */
+ if(H5S_select_release(space)<0) {
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL,
+ "can't release hyperslab");
+ } /* end if */
+
+ /* Copy all the per-dimension selection info into the space descriptor */
+ if((diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank,0))==NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector");
+ } /* end if */
+ for(i=0; i<space->extent.u.simple.rank; i++) {
+ diminfo[i].start = start[i];
+ diminfo[i].stride = stride[i];
+ diminfo[i].count = count[i];
+ diminfo[i].block = block[i];
+ } /* end for */
+ space->select.sel_info.hslab.diminfo = diminfo;
+
+ /* Set the number of elements in the hyperslab selection */
+ for(space->select.num_elem=1,i=0; i<space->extent.u.simple.rank; i++)
+ space->select.num_elem*=block[i]*count[i];
+ } /* end if */
+ else if(op==H5S_SELECT_OR) {
+ switch(space->select.type) {
+ case H5S_SEL_ALL:
+ /* break out now, 'or'ing with an all selection leaves the all selection */
+ HGOTO_DONE(SUCCEED);
+ break;
+
+ case H5S_SEL_HYPERSLABS:
+ /* Is this the first 'or' operation? */
+ if(space->select.sel_info.hslab.diminfo != NULL) {
+ /* yes, a "regular" hyperslab is selected currently */
+
+ hssize_t tmp_start[H5O_LAYOUT_NDIMS];
+ hsize_t tmp_stride[H5O_LAYOUT_NDIMS];
+ hsize_t tmp_count[H5O_LAYOUT_NDIMS];
+ hsize_t tmp_block[H5O_LAYOUT_NDIMS];
+
+ /* Generate the hyperslab information for the regular hyperslab */
+
+ /* Copy over the 'diminfo' information */
+ for(i=0; i<space->extent.u.simple.rank; i++) {
+ tmp_start[i]=space->select.sel_info.hslab.diminfo[i].start;
+ tmp_stride[i]=space->select.sel_info.hslab.diminfo[i].stride;
+ tmp_count[i]=space->select.sel_info.hslab.diminfo[i].count;
+ tmp_block[i]=space->select.sel_info.hslab.diminfo[i].block;
+ } /* end for */
+
+ /* Reset the number of selection elements */
+ space->select.num_elem=0;
+
+ /* Build the hyperslab information */
+ H5S_generate_hyperslab (space, H5S_SELECT_SET, tmp_start, tmp_stride, tmp_count, tmp_block);
+
+ /* Remove the 'diminfo' information, since we're adding to it */
+ H5FL_ARR_FREE(H5S_hyper_dim_t,space->select.sel_info.hslab.diminfo);
+ space->select.sel_info.hslab.diminfo = NULL;
+
+ /* Add in the new hyperslab information */
+ H5S_generate_hyperslab (space, op, start, stride, count, block);
+ } /* end if */
+ else {
+ /* nope, an "irregular" hyperslab is selected currently */
+ /* Add in the new hyperslab information */
+ H5S_generate_hyperslab (space, op, start, stride, count, block);
+ } /* end else */
+ break;
+
+ default:
+ HRETURN_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation");
+ } /* end switch() */
+ } /* end if */
+ else {
+ HRETURN_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation");
+ } /* end else */
+
/* Set selection type */
space->select.type=H5S_SEL_HYPERSLABS;
+
ret_value=SUCCEED;
done:
@@ -3225,7 +4527,7 @@ done:
if(_block!=NULL)
H5FL_ARR_FREE(hsize_t,_block);
FUNC_LEAVE (ret_value);
-}
+} /* end H5S_select_hyperslab() */
/*--------------------------------------------------------------------------
@@ -3403,6 +4705,174 @@ H5S_hyper_select_iterate_mem (intn dim, H5S_hyper_iter_info_t *iter_info)
/*--------------------------------------------------------------------------
NAME
+ H5S_hyper_select_iterate_mem_opt
+ PURPOSE
+ Iterate over the data points in a regular hyperslab selection, calling a
+ user's function for each element.
+ USAGE
+ herr_t H5S_hyper_select_iterate_mem_opt(buf, type_id, space, op, operator_data)
+ H5S_sel_iter_t *iter; IN/OUT: Selection iterator
+ void *buf; IN/OUT: Buffer containing elements to iterate over
+ hid_t type_id; IN: Datatype ID of BUF array.
+ H5S_t *space; IN: Dataspace object containing selection to iterate over
+ H5D_operator_t op; IN: Function pointer to the routine to be
+ called for each element in BUF iterated over.
+ void *op_data; IN/OUT: Pointer to any user-defined data associated
+ with the operation.
+ RETURNS
+ Returns the return value of the last operator if it was non-zero, or zero
+ if all elements were processed. Otherwise returns a negative value.
+ DESCRIPTION
+ Iterates over the selected elements in a memory buffer, calling the user's
+ callback function for each element. The selection in the dataspace is
+ modified so that any elements already iterated over are removed from the
+ selection if the iteration is interrupted (by the H5D_operator_t function
+ returning non-zero) in the "middle" of the iteration and may be re-started
+ by the user where it left off.
+
+ NOTE: Until "subtracting" elements from a selection is implemented,
+ the selection is not modified.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S_hyper_select_iterate_mem_opt(H5S_sel_iter_t *iter, void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op,
+ void *op_data)
+{
+ 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 */
+ hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */
+ hsize_t slab[H5O_LAYOUT_NDIMS]; /* Size of objects in buffer */
+ size_t elem_size; /* Size of data element in buffer */
+ size_t temp_off; /* Offset in a given dimension */
+ uint8_t *loc; /* Current element location */
+ intn i; /* Counter */
+ intn fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ intn temp_dim; /* Temporary rank holder */
+ intn ndims; /* Rank of the dataspace */
+ herr_t user_ret=0; /* User's return value */
+
+ FUNC_ENTER (H5S_hyper_select_iterate_mem_opt, FAIL);
+
+ /* Set some convienence values */
+ ndims=space->extent.u.simple.rank;
+ fast_dim=ndims-1;
+ diminfo=space->select.sel_info.hslab.diminfo;
+
+ /* Get the data element size */
+ elem_size=H5Tget_size(type_id);
+
+ /* Elements in the fastest dimension are 'elem_size' */
+ slab[ndims-1]=elem_size;
+
+ /* If we have two or more dimensions, build the other dimension's element sizes */
+ if(ndims>=2) {
+ /* Build the table of next-dimension down 'element' sizes */
+ for(i=ndims-2; i>=0; i--)
+ slab[i]=slab[i+1]*space->extent.u.simple.size[i+1];
+ } /* end if */
+
+ /* Build the tables of count & block sizes as well as the initial offset */
+ for(i=0; i<ndims; i++) {
+ tmp_count[i]=diminfo[i].count;
+ tmp_block[i]=diminfo[i].block;
+ offset[i]=diminfo[i].start;
+ } /* end for */
+
+ /* Initialize the starting location */
+ for(loc=buf,i=0; i<ndims; i++)
+ loc+=diminfo[i].start*slab[i];
+
+ /* Go iterate over the hyperslabs */
+ while(user_ret==0) {
+ /* Iterate over the blocks in the fastest dimension */
+ while(tmp_count[fast_dim]>0 && user_ret==0) {
+
+ /* Iterate over the elements in the fastest dimension */
+ while(tmp_block[fast_dim]>0 && user_ret==0) {
+ user_ret=(*op)(loc,type_id,ndims,offset,op_data);
+
+ /* Increment the buffer location */
+ loc+=slab[fast_dim];
+
+ /* Increment the offset in the dataspace */
+ offset[fast_dim]++;
+
+ /* Decrement the sequence count */
+ tmp_block[fast_dim]--;
+ } /* end while */
+
+ /* Reset the sequence count */
+ tmp_block[fast_dim]=diminfo[fast_dim].block;
+
+ /* Move the location to the next sequence to start */
+ loc+=(diminfo[fast_dim].stride-diminfo[fast_dim].block)*slab[fast_dim];
+
+ /* Move the offset to the next sequence to start */
+ offset[fast_dim]+=(diminfo[fast_dim].stride-diminfo[fast_dim].block);
+
+ /* Decrement the block count */
+ tmp_count[fast_dim]--;
+ } /* end while */
+
+ /* Work on other dimensions if necessary */
+ if(fast_dim>0 && user_ret==0) {
+ /* Reset the sequence and block counts */
+ tmp_block[fast_dim]=diminfo[fast_dim].block;
+ 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;
+
+ /* Check for getting out of iterator */
+ if(temp_dim==0)
+ goto done; /* Yes, an evil goto.. :-) -QAK */
+
+ /* 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 */
+ } /* end if */
+
+ /* Re-compute buffer location & offset array */
+ for(loc=buf,i=0; i<ndims; i++) {
+ temp_off=diminfo[i].start
+ +diminfo[i].stride*(diminfo[i].count-tmp_count[i])
+ +(diminfo[i].block-tmp_block[i]);
+ loc+=temp_off*slab[i];
+ offset[i]=temp_off;
+ } /* end for */
+ } /* end while */
+
+done:
+ FUNC_LEAVE (user_ret);
+} /* end H5S_hyper_select_iterate_mem_opt() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_hyper_select_iterate
PURPOSE
Iterate over a hyperslab selection, calling a user's function for each
@@ -3450,33 +4920,37 @@ H5S_hyper_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t
assert(op);
assert(H5I_DATATYPE == H5I_get_type(type_id));
- /* Initialize these before any errors can occur */
- HDmemset(&iter,0,sizeof(H5S_sel_iter_t));
-
/* Initialize the selection iterator */
if (H5S_hyper_init(NULL, space, &iter, &min_elem_out)<0) {
HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL,
"unable to initialize selection information");
}
- /* Initialize parameter block for recursive calls */
- iter_info.dt=type_id;
- iter_info.elem_size=H5Tget_size(type_id);
- iter_info.space=space;
- iter_info.iter=&iter;
- iter_info.src=buf;
+ /* Check for the special case of just one H5Sselect_hyperslab call made */
+ if(space->select.sel_info.hslab.diminfo!=NULL) {
+ /* Use optimized call to iterate over regular hyperslab */
+ ret_value=H5S_hyper_select_iterate_mem_opt(&iter,buf,type_id,space,op,operator_data);
+ }
+ else {
+ /* Initialize parameter block for recursive calls */
+ iter_info.dt=type_id;
+ iter_info.elem_size=H5Tget_size(type_id);
+ iter_info.space=space;
+ iter_info.iter=&iter;
+ iter_info.src=buf;
- /* Set up the size of the memory space */
- HDmemcpy(iter_info.mem_size, space->extent.u.simple.size, space->extent.u.simple.rank*sizeof(hsize_t));
- iter_info.mem_size[space->extent.u.simple.rank]=iter_info.elem_size;
+ /* Set up the size of the memory space */
+ HDmemcpy(iter_info.mem_size, space->extent.u.simple.size, space->extent.u.simple.rank*sizeof(hsize_t));
+ iter_info.mem_size[space->extent.u.simple.rank]=iter_info.elem_size;
- /* Copy the location of the region in the file */
- iter_info.op=op;
- iter_info.op_data=operator_data;
+ /* Copy the location of the region in the file */
+ iter_info.op=op;
+ iter_info.op_data=operator_data;
- /* Recursively input the hyperslabs currently defined */
- /* starting with the slowest changing dimension */
- ret_value=H5S_hyper_select_iterate_mem(-1,&iter_info);
+ /* Recursively input the hyperslabs currently defined */
+ /* starting with the slowest changing dimension */
+ ret_value=H5S_hyper_select_iterate_mem(-1,&iter_info);
+ } /* end else */
/* Release selection iterator */
H5S_sel_iter_release(space,&iter);
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index 4c80cb3..08f3752 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -590,12 +590,20 @@ static hssize_t
H5S_get_select_hyper_nblocks(H5S_t *space)
{
hssize_t ret_value=FAIL; /* return value */
+ intn i; /* Counter */
FUNC_ENTER (H5S_get_select_hyper_nblocks, FAIL);
assert(space);
- ret_value = (hssize_t)space->select.sel_info.hslab.hyper_lst->count;
+ /* Check for a "regular" hyperslab selection */
+ if(space->select.sel_info.hslab.diminfo != NULL) {
+ /* Check each dimension */
+ for(ret_value=1,i=0; i<space->extent.u.simple.rank; i++)
+ ret_value*=space->select.sel_info.hslab.diminfo[i].count;
+ } /* end if */
+ else
+ ret_value = (hssize_t)space->select.sel_info.hslab.hyper_lst->count;
FUNC_LEAVE (ret_value);
} /* H5Sget_select_hyper_nblocks() */
@@ -742,8 +750,17 @@ H5Sget_select_elem_npoints(hid_t spaceid)
static herr_t
H5S_get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, hsize_t numblocks, hsize_t *buf)
{
+ H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
+ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */
+ hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */
+ size_t temp_off; /* Offset in a given dimension */
H5S_hyper_node_t *node; /* Hyperslab node */
intn rank; /* Dataspace rank */
+ intn i; /* Counter */
+ intn fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ intn temp_dim; /* Temporary rank holder */
+ intn ndims; /* Rank of the dataspace */
+ intn done; /* Whether we are done with the iteration */
herr_t ret_value=SUCCEED; /* return value */
FUNC_ENTER (H5S_get_select_hyper_blocklist, FAIL);
@@ -754,24 +771,107 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, hsize_t numbloc
/* Get the dataspace extent rank */
rank=space->extent.u.simple.rank;
- /* Get the head of the hyperslab list */
- node=space->select.sel_info.hslab.hyper_lst->head;
-
- /* Get to the correct first node to give back to the user */
- while(node!=NULL && startblock>0) {
- startblock--;
- node=node->next;
- } /* end while */
-
- /* Iterate through the node, copying each hyperslab's information */
- while(node!=NULL && numblocks>0) {
- HDmemcpy(buf,node->start,sizeof(hsize_t)*rank);
- buf+=rank;
- HDmemcpy(buf,node->end,sizeof(hsize_t)*rank);
- buf+=rank;
- numblocks--;
- node=node->next;
- } /* end while */
+ /* Check for a "regular" hyperslab selection */
+ if(space->select.sel_info.hslab.diminfo != NULL) {
+ /* Set some convienence values */
+ ndims=space->extent.u.simple.rank;
+ fast_dim=ndims-1;
+ diminfo=space->select.sel_info.hslab.diminfo;
+
+ /* Build the tables of count sizes as well as the initial offset */
+ for(i=0; i<ndims; i++) {
+ tmp_count[i]=diminfo[i].count;
+ offset[i]=diminfo[i].start;
+ } /* end for */
+
+ /* We're not done with the iteration */
+ done=0;
+
+ /* Go iterate over the hyperslabs */
+ while(done==0 && numblocks>0) {
+ /* Iterate over the blocks in the fastest dimension */
+ while(tmp_count[fast_dim]>0 && numblocks>0) {
+
+ /* Check if we should copy this block information */
+ if(startblock==0) {
+ /* Copy the starting location */
+ HDmemcpy(buf,offset,sizeof(hsize_t)*ndims);
+ buf+=ndims;
+
+ /* Compute the ending location */
+ HDmemcpy(buf,offset,sizeof(hsize_t)*ndims);
+ for(i=0; i<ndims; i++)
+ buf[i]+=(diminfo[i].block-1);
+ buf+=ndims;
+
+ /* Decrement the number of blocks to retrieve */
+ numblocks--;
+ } /* end if */
+ else
+ startblock--;
+
+ /* Move the offset to the next sequence to start */
+ offset[fast_dim]+=diminfo[fast_dim].stride;
+
+ /* Decrement the block count */
+ tmp_count[fast_dim]--;
+ } /* end while */
+
+ /* Work on other dimensions if necessary */
+ if(fast_dim>0 && numblocks>0) {
+ /* Reset the 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 && done==0) {
+ /* Decrement the block count */
+ tmp_count[temp_dim]--;
+
+ /* Check if we have more blocks left */
+ if(tmp_count[temp_dim]>0)
+ break;
+
+ /* Check for getting out of iterator */
+ if(temp_dim==0)
+ done=1;
+
+ /* 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 */
+ } /* end if */
+
+ /* Re-compute offset array */
+ for(i=0; i<ndims; i++) {
+ temp_off=diminfo[i].start
+ +diminfo[i].stride*(diminfo[i].count-tmp_count[i]);
+ offset[i]=temp_off;
+ } /* end for */
+ } /* end while */
+ } /* end if */
+ else {
+ /* Get the head of the hyperslab list */
+ node=space->select.sel_info.hslab.hyper_lst->head;
+
+ /* Get to the correct first node to give back to the user */
+ while(node!=NULL && startblock>0) {
+ startblock--;
+ node=node->next;
+ } /* end while */
+
+ /* Iterate through the node, copying each hyperslab's information */
+ while(node!=NULL && numblocks>0) {
+ HDmemcpy(buf,node->start,sizeof(hsize_t)*rank);
+ buf+=rank;
+ HDmemcpy(buf,node->end,sizeof(hsize_t)*rank);
+ buf+=rank;
+ numblocks--;
+ node=node->next;
+ } /* end while */
+ } /* end else */
FUNC_LEAVE (ret_value);
} /* H5Sget_select_hyper_blocklist() */