diff options
Diffstat (limited to 'src/H5Spoint.c')
-rw-r--r-- | src/H5Spoint.c | 181 |
1 files changed, 176 insertions, 5 deletions
diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 24dfe2a..cb7e98f 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -49,6 +49,8 @@ static htri_t H5S_point_is_contiguous(const H5S_t *space); static htri_t H5S_point_is_single(const H5S_t *space); static htri_t H5S_point_is_regular(const H5S_t *space); static herr_t H5S_point_adjust_u(H5S_t *space, const hsize_t *offset); +static herr_t H5S_point_project_scalar(const H5S_t *space, hsize_t *offset); +static herr_t H5S_point_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset); static herr_t H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space); /* Selection iteration callbacks */ @@ -78,6 +80,8 @@ const H5S_select_class_t H5S_sel_point[1] = {{ H5S_point_is_single, H5S_point_is_regular, H5S_point_adjust_u, + H5S_point_project_scalar, + H5S_point_project_simple, H5S_point_iter_init, }}; @@ -610,18 +614,18 @@ H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t UNUSED share_selection) /* Allocate room for the head of the point list */ if(NULL == (dst->select.sel_info.pnt_lst = H5FL_MALLOC(H5S_pnt_list_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node") + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point list node") curr = src->select.sel_info.pnt_lst->head; new_tail = NULL; while(curr) { /* Create new point */ if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node") + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") new_node->next = NULL; - if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(src->extent.rank*sizeof(hsize_t)))) { + if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(src->extent.rank * sizeof(hsize_t)))) { new_node = H5FL_FREE(H5S_pnt_node_t, new_node); - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information") + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") } /* end if */ /* Copy over the point's coordinates */ @@ -976,7 +980,7 @@ H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoint node = node->next; } /* end while */ - /* Iterate through the node, copying each hyperslab's information */ + /* Iterate through the node, copying each point's information */ while(node != NULL && numpoints > 0) { HDmemcpy(buf, node->pnt, sizeof(hsize_t) * rank); buf += rank; @@ -1346,6 +1350,173 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset) } /* H5S_point_adjust_u() */ +/*------------------------------------------------------------------------- + * Function: H5S_point_project_scalar + * + * Purpose: Projects a single element point selection into a scalar + * dataspace + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_point_project_scalar(const H5S_t *space, hsize_t *offset) +{ + const H5S_pnt_node_t *node; /* Point node */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_point_project_scalar) + + /* Check args */ + HDassert(space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(space)); + HDassert(offset); + + /* Get the head of the point list */ + node = space->select.sel_info.pnt_lst->head; + + /* Check for more than one point selected */ + if(node->next) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "point selection of one element has more than one node!") + + /* Calculate offset of selection in projected buffer */ + *offset = H5V_array_offset(space->extent.rank, space->extent.size, node->pnt); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_point_project_scalar() */ + + +/*------------------------------------------------------------------------- + * Function: H5S_point_project_simple + * + * Purpose: Projects a point selection onto/into a simple dataspace + * of a different rank + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset) +{ + const H5S_pnt_node_t *base_node; /* Point node in base space */ + 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 */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_point_project_simple) + + /* Check args */ + HDassert(base_space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(base_space)); + HDassert(new_space); + HDassert(offset); + + /* We are setting a new selection, remove any current selection in new dataspace */ + if(H5S_SELECT_RELEASE(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") + + /* Allocate room for the head of the point list */ + if(NULL == (new_space->select.sel_info.pnt_lst = H5FL_MALLOC(H5S_pnt_list_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point list node") + + /* Check if the new space's rank is < or > base space's rank */ + if(new_space->extent.rank < base_space->extent.rank) { + hsize_t block[H5S_MAX_RANK]; /* Block selected in base dataspace */ + + /* Compute the difference in ranks */ + rank_diff = base_space->extent.rank - new_space->extent.rank; + + /* Calculate offset of selection in projected buffer */ + HDmemset(block, 0, sizeof(block)); + HDmemcpy(block, base_space->select.sel_info.pnt_lst->head->pnt, sizeof(hsize_t) * rank_diff); + *offset = H5V_array_offset(base_space->extent.rank, base_space->extent.size, block); + + /* Iterate through base space's point nodes, copying the point information */ + base_node = base_space->select.sel_info.pnt_lst->head; + prev_node = NULL; + while(base_node) { + /* Create new point */ + if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") + new_node->next = NULL; + if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(new_space->extent.rank * sizeof(hsize_t)))) { + new_node = H5FL_FREE(H5S_pnt_node_t, new_node); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") + } /* end if */ + + /* Copy over the point's coordinates */ + HDmemcpy(new_node->pnt, &base_node->pnt[rank_diff], (new_space->extent.rank * sizeof(hsize_t))); + + /* Keep the order the same when copying */ + if(NULL == prev_node) + prev_node = new_space->select.sel_info.pnt_lst->head = new_node; + else { + prev_node->next = new_node; + prev_node = new_node; + } /* end else */ + + /* Advance to next node */ + base_node = base_node->next; + } /* end while */ + } /* end if */ + else { + HDassert(new_space->extent.rank > base_space->extent.rank); + + /* Compute the difference in ranks */ + rank_diff = new_space->extent.rank - base_space->extent.rank; + + /* The offset is zero when projected into higher dimensions */ + *offset = 0; + + /* Iterate through base space's point nodes, copying the point information */ + base_node = base_space->select.sel_info.pnt_lst->head; + prev_node = NULL; + while(base_node) { + /* Create new point */ + if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") + new_node->next = NULL; + if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(new_space->extent.rank * sizeof(hsize_t)))) { + new_node = H5FL_FREE(H5S_pnt_node_t, new_node); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") + } /* end if */ + + /* Copy over the point's coordinates */ + HDmemset(new_node->pnt, 0, sizeof(hsize_t) * rank_diff); + HDmemcpy(&new_node->pnt[rank_diff], base_node->pnt, (new_space->extent.rank * sizeof(hsize_t))); + + /* Keep the order the same when copying */ + if(NULL == prev_node) + prev_node = new_space->select.sel_info.pnt_lst->head = new_node; + else { + prev_node->next = new_node; + prev_node = new_node; + } /* end else */ + + /* Advance to next node */ + base_node = base_node->next; + } /* end while */ + } /* end else */ + + /* Number of elements selected will be the same */ + new_space->select.num_elem = base_space->select.num_elem; + + /* Set selection type */ + new_space->select.type = H5S_sel_point; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_point_project_simple() */ + + /*-------------------------------------------------------------------------- NAME H5Sselect_elements |