summaryrefslogtreecommitdiffstats
path: root/src/H5Spoint.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2014-06-13 06:23:57 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2014-06-13 06:23:57 (GMT)
commit4ccb865c70f977a4a97d75df3d6e792c8cbdfdd8 (patch)
tree860f585f1589250b03aec29371acb13ebbf2e022 /src/H5Spoint.c
parentc2bc22d51cdf528c9b04ec115ac22c7e79fd7c6d (diff)
downloadhdf5-4ccb865c70f977a4a97d75df3d6e792c8cbdfdd8.zip
hdf5-4ccb865c70f977a4a97d75df3d6e792c8cbdfdd8.tar.gz
hdf5-4ccb865c70f977a4a97d75df3d6e792c8cbdfdd8.tar.bz2
[svn-r25273] Description:
Bring in Chao/Neil/my changes to optimize hyperslab selection operations further, along with 3 new public API routines: H5Scombine_hyperslab(), H5Sselect_select() and H5Scombine_select(), along with many minor cleanups to the code and fixing a few compiler warnings. Tested on: Mac OSX/64 10.9.3 w/gcc 4.9.x and parallel w/OpenMPI (h5commttest forthcoming)
Diffstat (limited to 'src/H5Spoint.c')
-rw-r--r--src/H5Spoint.c150
1 files changed, 86 insertions, 64 deletions
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index 70842df..d6b26fa 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -17,7 +17,7 @@
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* Tuesday, June 16, 1998
*
- * Purpose: Point selection data space I/O functions.
+ * Purpose: Point selection dataspace I/O functions.
*/
#define H5S_PACKAGE /*suppress error about including H5Spkg */
@@ -400,6 +400,8 @@ H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *co
HDassert(op == H5S_SELECT_SET || op == H5S_SELECT_APPEND || op == H5S_SELECT_PREPEND);
for(u = 0; u < num_elem; u++) {
+ unsigned dim; /* Counter for dimensions */
+
/* Allocate space for the new node */
if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node")
@@ -418,31 +420,45 @@ H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *co
else
curr->next = new_node;
curr = new_node;
+
+ /**
+ * Note: when op is H5S_SELECT_SET, the bound box has been reset
+ * inside H5S_select_elements, the only caller of this function.
+ * So the following bound box update procedure works correctly
+ * for the SET operation.
+ */
+ /* update bound box */
+ for(dim = 0; dim < space->extent.rank; dim++) {
+ space->select.low_bounds[dim] = MIN(space->select.low_bounds[dim], curr->pnt[dim]);
+ space->select.high_bounds[dim] = MAX(space->select.high_bounds[dim], curr->pnt[dim]);
+ } /* end for */
} /* end for */
new_node = NULL;
/* Insert the list of points selected in the proper place */
if(op == H5S_SELECT_SET || op == H5S_SELECT_PREPEND) {
/* Append current list, if there is one */
- if(space->select.sel_info.pnt_lst->head != NULL)
+ if(NULL != space->select.sel_info.pnt_lst->head)
curr->next = space->select.sel_info.pnt_lst->head;
/* Put new list in point selection */
space->select.sel_info.pnt_lst->head = top;
+
+ /* Change the tail pointer if tail has not been set */
+ if(NULL == space->select.sel_info.pnt_lst->tail)
+ space->select.sel_info.pnt_lst->tail = curr;
} /* end if */
else { /* op==H5S_SELECT_APPEND */
H5S_pnt_node_t *tmp_node; /* Temporary point selection node */
tmp_node = space->select.sel_info.pnt_lst->head;
if(tmp_node != NULL) {
- while(tmp_node->next != NULL)
- tmp_node = tmp_node->next;
-
- /* Append new list to point selection */
- tmp_node->next = top;
+ HDassert(space->select.sel_info.pnt_lst->tail);
+ space->select.sel_info.pnt_lst->tail->next = top;
} /* end if */
else
space->select.sel_info.pnt_lst->head = top;
+ space->select.sel_info.pnt_lst->tail = curr;
} /* end else */
/* Set the number of elements in the new selection */
@@ -566,10 +582,17 @@ H5S_select_elements(H5S_t *space, H5S_seloper_t op, size_t num_elem,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release point selection")
/* Allocate space for the point selection information if necessary */
- if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS || space->select.sel_info.pnt_lst == NULL)
+ if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS || space->select.sel_info.pnt_lst == NULL) {
+ hsize_t tmp = HSIZET_MAX;
+
if(NULL == (space->select.sel_info.pnt_lst = H5FL_CALLOC(H5S_pnt_list_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate element information")
+ /* Set the bound box to the default value */
+ H5VM_array_fill(space->select.low_bounds, &tmp, sizeof(hsize_t), space->extent.rank);
+ HDmemset(space->select.high_bounds, 0, sizeof(hsize_t) * space->extent.rank);
+ } /* end if */
+
/* Add points to selection */
if(H5S_point_add(space, op, num_elem, coord) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert elements")
@@ -641,6 +664,7 @@ H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t UNUSED share_selection)
curr = curr->next;
} /* end while */
+ dst->select.sel_info.pnt_lst->tail = new_tail;
done:
if(ret_value < 0 && dst->select.sel_info.pnt_lst) {
@@ -684,28 +708,21 @@ done:
static htri_t
H5S_point_is_valid (const H5S_t *space)
{
- H5S_pnt_node_t *curr; /* Point information nodes */
- unsigned u; /* Counter */
- htri_t ret_value=TRUE; /* return value */
+ unsigned u; /* Counter */
+ htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(space);
- /* Check each point to determine whether selection+offset is within extent */
- curr = space->select.sel_info.pnt_lst->head;
- while(curr != NULL) {
- /* Check each dimension */
- for(u = 0; u < space->extent.rank; u++) {
- /* Check if an offset has been defined */
- /* Bounds check the selected point + offset against the extent */
- if(((curr->pnt[u] + (hsize_t)space->select.offset[u]) > space->extent.size[u])
- || (((hssize_t)curr->pnt[u] + space->select.offset[u]) < 0))
- HGOTO_DONE(FALSE)
- } /* end for */
-
- curr = curr->next;
- } /* end while */
+ /* Check each dimension */
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Bounds check the selected point + offset against the extent */
+ if((space->select.high_bounds[u] + (hsize_t)space->select.offset[u]) > space->extent.size[u])
+ HGOTO_DONE(FALSE)
+ if(((hssize_t)space->select.low_bounds[u] + space->select.offset[u]) < 0)
+ HGOTO_DONE(FALSE)
+ } /* end for */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -740,7 +757,7 @@ H5Sget_select_elem_npoints(hid_t spaceid)
/* Check args */
if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an element selection")
@@ -773,7 +790,6 @@ done:
static hssize_t
H5S_point_serial_size (const H5S_t *space)
{
- H5S_pnt_node_t *curr; /* Point information nodes */
hssize_t ret_value; /* return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -784,15 +800,11 @@ H5S_point_serial_size (const H5S_t *space)
* <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> +
* <length (4 bytes)> + <rank (4 bytes)> + <# of points (4 bytes)> = 24 bytes
*/
- ret_value=24;
+ ret_value = 24;
/* Count points in selection */
- curr=space->select.sel_info.pnt_lst->head;
- while(curr!=NULL) {
- /* Add 4 bytes times the rank for each element selected */
- ret_value+=4*space->extent.rank;
- curr=curr->next;
- } /* end while */
+ /* (Add 4 bytes times the rank for each element selected) */
+ ret_value += (4 * space->extent.rank) * (hssize_t)H5S_GET_SELECT_NPOINTS(space);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_point_serial_size() */
@@ -1035,7 +1047,7 @@ H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint,
if(NULL == buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer")
if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a point selection")
@@ -1075,41 +1087,29 @@ done:
static herr_t
H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
{
- H5S_pnt_node_t *node; /* Point node */
- unsigned rank; /* Dataspace rank */
- unsigned u; /* index variable */
- herr_t ret_value = SUCCEED; /* Return value */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
+ /* Sanity check */
HDassert(space);
HDassert(start);
HDassert(end);
- /* Get the dataspace extent rank */
- rank = space->extent.rank;
-
- /* Set the start and end arrays up */
- for(u = 0; u < rank; u++) {
- start[u] = HSIZET_MAX;
- end[u] = 0;
- } /* end for */
+ /* Loop over dimensions */
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Sanity check */
+ HDassert(space->select.low_bounds[u] <= space->select.high_bounds[u]);
- /* Iterate through the node, checking the bounds on each element */
- node = space->select.sel_info.pnt_lst->head;
- while(node != NULL) {
- for(u = 0; u < rank; u++) {
- /* Check for offset moving selection negative */
- if(((hssize_t)node->pnt[u] + space->select.offset[u]) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
+ /* Check for offset moving selection negative */
+ if(((hssize_t)space->select.low_bounds[u] + space->select.offset[u]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
- if(start[u] > (node->pnt[u] + space->select.offset[u]))
- start[u] = node->pnt[u] + space->select.offset[u];
- if(end[u] < (node->pnt[u] + space->select.offset[u]))
- end[u] = node->pnt[u] + space->select.offset[u];
- } /* end for */
- node = node->next;
- } /* end while */
+ /* Set the low & high bounds in this dimension */
+ start[u] = (hsize_t)((hssize_t)space->select.low_bounds[u] + space->select.offset[u]);
+ end[u] = (hsize_t)((hssize_t)space->select.high_bounds[u] + space->select.offset[u]);
+ } /* end for */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1321,6 +1321,7 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset)
{
H5S_pnt_node_t *node; /* Point node */
unsigned rank; /* Dataspace rank */
+ unsigned u; /* Local index variable */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -1331,8 +1332,6 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset)
node = space->select.sel_info.pnt_lst->head;
rank = space->extent.rank;
while(node) {
- unsigned u; /* Local index variable */
-
/* Adjust each coordinate for point node */
for(u = 0; u < rank; u++) {
/* Check for offset moving selection negative */
@@ -1346,6 +1345,12 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset)
node = node->next;
} /* end while */
+ /* update the bound box of the selection */
+ for(u = 0; u < rank; u++) {
+ space->select.low_bounds[u] -= offset[u];
+ space->select.high_bounds[u] -= offset[u];
+ } /* end for */
+
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5S_point_adjust_u() */
@@ -1410,6 +1415,7 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off
H5S_pnt_node_t *new_node; /* Point node in new space */
H5S_pnt_node_t *prev_node; /* Previous point node in new space */
unsigned rank_diff; /* Difference in ranks between spaces */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -1466,6 +1472,12 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off
/* Advance to next node */
base_node = base_node->next;
} /* end while */
+
+ /* Update the bounding box */
+ for(u = 0; u < new_space->extent.rank; u++) {
+ new_space->select.low_bounds[u] = base_space->select.low_bounds[u + rank_diff];
+ new_space->select.high_bounds[u] = base_space->select.high_bounds[u + rank_diff];
+ } /* end for */
} /* end if */
else {
HDassert(new_space->extent.rank > base_space->extent.rank);
@@ -1504,6 +1516,16 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off
/* Advance to next node */
base_node = base_node->next;
} /* end while */
+
+ /* Update the bounding box */
+ for(u = 0; u < rank_diff; u++) {
+ new_space->select.low_bounds[u] = 0;
+ new_space->select.high_bounds[u] = 0;
+ } /* end for */
+ for(; u < new_space->extent.rank; u++) {
+ new_space->select.low_bounds[u] = base_space->select.low_bounds[u - rank_diff];
+ new_space->select.high_bounds[u] = base_space->select.high_bounds[u - rank_diff];
+ } /* end for */
} /* end else */
/* Number of elements selected will be the same */
@@ -1643,7 +1665,7 @@ H5S_point_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter,
/* Get the dataspace dimensions */
if((ndims = H5S_get_simple_extent_dims (space, dims, NULL)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to retrieve data space dimensions")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to retrieve dataspace dimensions")
/* Walk through the points in the selection, starting at the current */
/* location in the iterator */