From 54d42e74c4e5495887b85b720366a87eb1f3eb7d Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 10 Nov 2007 16:07:53 -0500 Subject: [svn-r14249] Description: - Changed H5S_select_shape_same routine to handle scalar dataspace comparisons correctly. (Added regression tests to verify) - Simplified chunk map creation, now that scalar dataspaces are handled in same way as "simple" dataspaces. Tested on: FreeBSD/32 6.2 (duty) in debug mode FreeBSD/64 6.2 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/default API=1.6.x, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Mac OS X/32 10.4.10 (amazon) in debug mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode --- src/H5Dio.c | 90 +++++--------- src/H5Dpkg.h | 1 - src/H5Sselect.c | 260 +++++++++++++++++++++-------------------- test/tselect.c | 355 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 516 insertions(+), 190 deletions(-) diff --git a/src/H5Dio.c b/src/H5Dio.c index 6a6d532..7dea928 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -2337,8 +2337,6 @@ H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *f const H5S_t *mem_space, fm_map *fm) { H5S_t *tmp_mspace = NULL; /* Temporary memory dataspace */ - H5S_t *equiv_mspace = NULL; /* Equivalent memory dataspace */ - hbool_t equiv_mspace_init = FALSE;/* Equivalent memory dataspace was created */ hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */ hbool_t file_space_normalized = FALSE; /* File dataspace was normalized */ hid_t f_tid = (-1); /* Temporary copy of file datatype for iteration */ @@ -2361,27 +2359,8 @@ H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *f /* Check if the memory space is scalar & make equivalent memory space */ if((sm_ndims = H5S_GET_EXTENT_NDIMS(mem_space)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number") - if(sm_ndims==0) { - hsize_t dims[H5O_LAYOUT_NDIMS]; /* Temporary dimension information */ - - /* Set up "equivalent" n-dimensional dataspace with size '1' in each dimension */ - for(u=0; ushared->layout.u.chunk.ndims-1; u++) - dims[u]=1; - if((equiv_mspace = H5S_create_simple(dataset->shared->layout.u.chunk.ndims-1,dims,NULL))==NULL) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create equivalent dataspace for scalar space") - - /* Indicate that this space needs to be released */ - equiv_mspace_init = TRUE; - - /* Set the number of dimensions for the memory dataspace */ - fm->m_ndims = dataset->shared->layout.u.chunk.ndims - 1; - } /* end else */ - else { - equiv_mspace = (H5S_t *)mem_space; /* Casting away 'const' OK... */ - - /* Set the number of dimensions for the memory dataspace */ - H5_ASSIGN_OVERFLOW(fm->m_ndims, sm_ndims, int, unsigned); - } /* end else */ + /* Set the number of dimensions for the memory dataspace */ + H5_ASSIGN_OVERFLOW(fm->m_ndims, sm_ndims, int, unsigned); /* Get dim number and dimensionality for each dataspace */ fm->f_ndims = f_ndims = dataset->shared->layout.u.chunk.ndims - 1; @@ -2436,13 +2415,12 @@ H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *f /* Point at the dataspaces */ fm->file_space = file_space; - fm->mem_space = equiv_mspace; - fm->mem_space_copy = equiv_mspace_init; /* Make certain to copy memory dataspace if necessary */ + fm->mem_space = mem_space; /* Get type of selection on disk & in memory */ if((fsel_type = H5S_GET_SELECT_TYPE(file_space)) < H5S_SEL_NONE) HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to convert from file to memory data space") - if((fm->msel_type = H5S_GET_SELECT_TYPE(equiv_mspace)) < H5S_SEL_NONE) + if((fm->msel_type = H5S_GET_SELECT_TYPE(mem_space)) < H5S_SEL_NONE) HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to convert from file to memory data space") /* If the selection is NONE or POINTS, set the flag to FALSE */ @@ -2451,21 +2429,8 @@ H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *f else sel_hyper_flag = TRUE; - /* Check if file selection is a point selection */ - if(!sel_hyper_flag) { - /* Create temporary datatypes for selection iteration */ - if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL))) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype") - - /* Spaces aren't the same shape, iterate over the memory selection directly */ - if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_file_cb, fm) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections") - - /* Reset "last chunk" info */ - fm->last_index=(hsize_t)-1; - fm->last_chunk_info=NULL; - } /* end if */ - else { + /* Check if file selection is a not a hyperslab selection */ + if(sel_hyper_flag) { /* Build the file selection for each chunk */ if(H5D_create_chunk_file_map_hyper(fm,dataset) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections") @@ -2486,12 +2451,25 @@ H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *f /* Get the next chunk node in the skip list */ curr_node=H5SL_next(curr_node); } /* end while */ + } /* end if */ + else { + /* Create temporary datatypes for selection iteration */ + if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL))) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype") + + /* Spaces might not be the same shape, iterate over the file selection directly */ + if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_file_cb, fm) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections") + + /* Reset "last chunk" info */ + fm->last_index=(hsize_t)-1; + fm->last_chunk_info=NULL; } /* end else */ /* Build the memory selection for each chunk */ - if(sel_hyper_flag && H5S_select_shape_same(file_space,equiv_mspace)==TRUE) { + if(sel_hyper_flag && H5S_select_shape_same(file_space, mem_space) == TRUE) { /* Reset chunk template information */ - fm->mchunk_tmpl=NULL; + fm->mchunk_tmpl = NULL; /* If the selections are the same shape, use the file chunk information * to generate the memory chunk information quickly. @@ -2503,7 +2481,7 @@ H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *f size_t elmt_size; /* Memory datatype size */ /* Make a copy of equivalent memory space */ - if((tmp_mspace = H5S_copy(equiv_mspace,TRUE))==NULL) + if((tmp_mspace = H5S_copy(mem_space, TRUE)) == NULL) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space") /* De-select the mem space copy */ @@ -2522,7 +2500,7 @@ H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *f /* Create selection iterator for memory selection */ if((elmt_size=H5T_get_size(mem_type))==0) HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid") - if (H5S_select_iter_init(&(fm->mem_iter), equiv_mspace, elmt_size) < 0) + if(H5S_select_iter_init(&(fm->mem_iter), mem_space, elmt_size) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") iter_init = TRUE; /* Selection iteration info has been initialized */ @@ -2567,10 +2545,6 @@ done: fm->file_space = NULL; fm->mem_space = NULL; - if(equiv_mspace_init && equiv_mspace) { - if(H5S_close(equiv_mspace) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template") - } /* end if */ if(iter_init) { if(H5S_SELECT_ITER_RELEASE(&(fm->mem_iter)) < 0) HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") @@ -2888,20 +2862,12 @@ H5D_create_chunk_mem_map_hyper(const fm_map *fm) chunk_info=H5SL_item(curr_node); assert(chunk_info); - /* Check if it's OK to share dataspace */ - if(fm->mem_space_copy) { - /* Copy the memory dataspace & selection to be the chunk's dataspace & selection */ - if((chunk_info->mspace = H5S_copy(fm->mem_space,FALSE))==NULL) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space") - } /* end if */ - else { - /* Just point at the memory dataspace & selection */ - /* (Casting away const OK -QAK) */ - chunk_info->mspace=(H5S_t *)fm->mem_space; + /* Just point at the memory dataspace & selection */ + /* (Casting away const OK -QAK) */ + chunk_info->mspace=(H5S_t *)fm->mem_space; - /* Indicate that the chunk's memory space is shared */ - chunk_info->mspace_shared=1; - } /* end else */ + /* Indicate that the chunk's memory space is shared */ + chunk_info->mspace_shared=1; } /* end if */ else { /* Get bounding box for file selection */ diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 34a32ee..7837d72 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -204,7 +204,6 @@ typedef struct fm_map { H5D_chunk_info_t *last_chunk_info; /* Pointer to last chunk's info */ const H5S_t *file_space; /* Pointer to the file dataspace */ const H5S_t *mem_space; /* Pointer to the memory dataspace */ - unsigned mem_space_copy; /* Flag to indicate that the memory dataspace must be copied */ hsize_t f_dims[H5O_LAYOUT_NDIMS]; /* File dataspace dimensions */ H5S_t *mchunk_tmpl; /* Dataspace template for new memory chunks */ unsigned f_ndims; /* Number of dimensions for file dataspace */ diff --git a/src/H5Sselect.c b/src/H5Sselect.c index e3b90bb..616efc0 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -1261,137 +1261,145 @@ H5S_get_select_type(const H5S_t *space) htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2) { - H5S_sel_iter_t iter1; /* Selection #1 iteration info */ - H5S_sel_iter_t iter2; /* Selection #2 iteration info */ - hbool_t iter1_init=0; /* Selection #1 iteration info has been initialized */ - hbool_t iter2_init=0; /* Selection #2 iteration info has been initialized */ - unsigned u; /* Index variable */ - htri_t ret_value=TRUE; /* return value */ + H5S_sel_iter_t iter1; /* Selection #1 iteration info */ + H5S_sel_iter_t iter2; /* Selection #2 iteration info */ + hbool_t iter1_init = 0; /* Selection #1 iteration info has been initialized */ + hbool_t iter2_init = 0; /* Selection #2 iteration info has been initialized */ + unsigned u; /* Index variable */ + htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI(H5S_select_shape_same, FAIL); + FUNC_ENTER_NOAPI(H5S_select_shape_same, FAIL) /* Check args */ - assert(space1); - assert(space2); - - /* Check for different dimensionality */ - if (space1->extent.rank!=space2->extent.rank) - HGOTO_DONE(FALSE); - - /* Check for different number of elements selected */ - if(H5S_GET_SELECT_NPOINTS(space1)!=H5S_GET_SELECT_NPOINTS(space2)) - HGOTO_DONE(FALSE); - - /* Check for "easy" cases before getting into generalized block iteration code */ - if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_ALL && H5S_GET_SELECT_TYPE(space2)==H5S_SEL_ALL) { - hsize_t dims1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */ - hsize_t dims2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */ - - if(H5S_get_simple_extent_dims(space1, dims1, NULL)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); - if(H5S_get_simple_extent_dims(space2, dims2, NULL)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); - - /* Check that the sizes are the same */ - for (u=0; uextent.rank; u++) - if(dims1[u]!=dims2[u]) - HGOTO_DONE(FALSE); + HDassert(space1); + HDassert(space2); + + /* Special case for one or both dataspaces being scalar */ + if(space1->extent.rank == 0 || space2->extent.rank == 0) { + /* Check for different number of elements selected */ + if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2)) + HGOTO_DONE(FALSE) } /* end if */ - else if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_NONE || H5S_GET_SELECT_TYPE(space2)==H5S_SEL_NONE) { - HGOTO_DONE(TRUE); - } /* end if */ - else if((H5S_GET_SELECT_TYPE(space1)==H5S_SEL_HYPERSLABS && space1->select.sel_info.hslab->diminfo_valid) - && (H5S_GET_SELECT_TYPE(space2)==H5S_SEL_HYPERSLABS && space2->select.sel_info.hslab->diminfo_valid)) { - - /* Check that the shapes are the same */ - for (u=0; uextent.rank; u++) { - if(space1->select.sel_info.hslab->opt_diminfo[u].stride!=space2->select.sel_info.hslab->opt_diminfo[u].stride) - HGOTO_DONE(FALSE); - if(space1->select.sel_info.hslab->opt_diminfo[u].count!=space2->select.sel_info.hslab->opt_diminfo[u].count) - HGOTO_DONE(FALSE); - if(space1->select.sel_info.hslab->opt_diminfo[u].block!=space2->select.sel_info.hslab->opt_diminfo[u].block) - HGOTO_DONE(FALSE); - } /* end for */ - } /* end if */ - /* Iterate through all the blocks in the selection */ else { - hsize_t start1[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #1 */ - hsize_t start2[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #2 */ - hsize_t end1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */ - hsize_t end2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */ - hsize_t off1[H5O_LAYOUT_NDIMS]; /* Offset of selection #1 blocks */ - hsize_t off2[H5O_LAYOUT_NDIMS]; /* Offset of selection #2 blocks */ - htri_t status1,status2; /* Status from next block checks */ - unsigned first_block=1; /* Flag to indicate the first block */ - - /* Initialize iterator for each dataspace selection - * Use '0' for element size instead of actual element size to indicate - * that the selection iterator shouldn't be "flattened", since we - * aren't actually going to be doing I/O with the iterators. - */ - if(H5S_select_iter_init(&iter1, space1, (size_t)0) < 0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - iter1_init = 1; - if(H5S_select_iter_init(&iter2, space2, (size_t)0) < 0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - iter2_init = 1; - - /* Iterate over all the blocks in each selection */ - while(1) { - /* Get the current block for each selection iterator */ - if(H5S_SELECT_ITER_BLOCK(&iter1,start1,end1)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block"); - if(H5S_SELECT_ITER_BLOCK(&iter2,start2,end2)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block"); - - /* The first block only compares the sizes and sets the relative offsets for later blocks */ - if(first_block) { - /* If the block sizes from each selection doesn't match, get out */ - for (u=0; uextent.rank; u++) { - if((end1[u]-start1[u])!=(end2[u]-start2[u])) - HGOTO_DONE(FALSE); - - /* Set the relative locations of the selections */ - off1[u]=start1[u]; - off2[u]=start2[u]; - } /* end for */ - - /* Reset "first block" flag */ - first_block=0; - } /* end if */ - else { - /* Check over the blocks for each selection */ - for (u=0; uextent.rank; u++) { - /* Check if the blocks are in the same relative location */ - if((start1[u]-off1[u])!=(start2[u]-off2[u])) - HGOTO_DONE(FALSE); - + /* Check for different dimensionality */ + if(space1->extent.rank != space2->extent.rank) + HGOTO_DONE(FALSE) + + /* Check for different number of elements selected */ + if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2)) + HGOTO_DONE(FALSE) + + /* Check for "easy" cases before getting into generalized block iteration code */ + if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_ALL && H5S_GET_SELECT_TYPE(space2)==H5S_SEL_ALL) { + hsize_t dims1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */ + hsize_t dims2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */ + + if(H5S_get_simple_extent_dims(space1, dims1, NULL)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); + if(H5S_get_simple_extent_dims(space2, dims2, NULL)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); + + /* Check that the sizes are the same */ + for (u=0; uextent.rank; u++) + if(dims1[u]!=dims2[u]) + HGOTO_DONE(FALSE); + } /* end if */ + else if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_NONE || H5S_GET_SELECT_TYPE(space2)==H5S_SEL_NONE) { + HGOTO_DONE(TRUE); + } /* end if */ + else if((H5S_GET_SELECT_TYPE(space1)==H5S_SEL_HYPERSLABS && space1->select.sel_info.hslab->diminfo_valid) + && (H5S_GET_SELECT_TYPE(space2)==H5S_SEL_HYPERSLABS && space2->select.sel_info.hslab->diminfo_valid)) { + + /* Check that the shapes are the same */ + for (u=0; uextent.rank; u++) { + if(space1->select.sel_info.hslab->opt_diminfo[u].stride!=space2->select.sel_info.hslab->opt_diminfo[u].stride) + HGOTO_DONE(FALSE); + if(space1->select.sel_info.hslab->opt_diminfo[u].count!=space2->select.sel_info.hslab->opt_diminfo[u].count) + HGOTO_DONE(FALSE); + if(space1->select.sel_info.hslab->opt_diminfo[u].block!=space2->select.sel_info.hslab->opt_diminfo[u].block) + HGOTO_DONE(FALSE); + } /* end for */ + } /* end if */ + /* Iterate through all the blocks in the selection */ + else { + hsize_t start1[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #1 */ + hsize_t start2[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #2 */ + hsize_t end1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */ + hsize_t end2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */ + hsize_t off1[H5O_LAYOUT_NDIMS]; /* Offset of selection #1 blocks */ + hsize_t off2[H5O_LAYOUT_NDIMS]; /* Offset of selection #2 blocks */ + htri_t status1,status2; /* Status from next block checks */ + unsigned first_block=1; /* Flag to indicate the first block */ + + /* Initialize iterator for each dataspace selection + * Use '0' for element size instead of actual element size to indicate + * that the selection iterator shouldn't be "flattened", since we + * aren't actually going to be doing I/O with the iterators. + */ + if(H5S_select_iter_init(&iter1, space1, (size_t)0) < 0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); + iter1_init = 1; + if(H5S_select_iter_init(&iter2, space2, (size_t)0) < 0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); + iter2_init = 1; + + /* Iterate over all the blocks in each selection */ + while(1) { + /* Get the current block for each selection iterator */ + if(H5S_SELECT_ITER_BLOCK(&iter1,start1,end1)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block"); + if(H5S_SELECT_ITER_BLOCK(&iter2,start2,end2)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block"); + + /* The first block only compares the sizes and sets the relative offsets for later blocks */ + if(first_block) { /* If the block sizes from each selection doesn't match, get out */ - if((end1[u]-start1[u])!=(end2[u]-start2[u])) - HGOTO_DONE(FALSE); - } /* end for */ - } /* end else */ - - /* Check if we are able to advance to the next selection block */ - if((status1=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter1))<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block"); - if((status2=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter2))<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block"); - - /* Did we run out of blocks at the same time? */ - if(status1==FALSE && status2==FALSE) - break; - else if(status1!=status2) { - HGOTO_DONE(FALSE); - } /* end if */ - else { - /* Advance to next block in selection iterators */ - if(H5S_SELECT_ITER_NEXT_BLOCK(&iter1)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block"); - if(H5S_SELECT_ITER_NEXT_BLOCK(&iter2)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block"); - } /* end else */ - } /* end while */ + for (u=0; uextent.rank; u++) { + if((end1[u]-start1[u])!=(end2[u]-start2[u])) + HGOTO_DONE(FALSE); + + /* Set the relative locations of the selections */ + off1[u]=start1[u]; + off2[u]=start2[u]; + } /* end for */ + + /* Reset "first block" flag */ + first_block=0; + } /* end if */ + else { + /* Check over the blocks for each selection */ + for (u=0; uextent.rank; u++) { + /* Check if the blocks are in the same relative location */ + if((start1[u]-off1[u])!=(start2[u]-off2[u])) + HGOTO_DONE(FALSE); + + /* If the block sizes from each selection doesn't match, get out */ + if((end1[u]-start1[u])!=(end2[u]-start2[u])) + HGOTO_DONE(FALSE); + } /* end for */ + } /* end else */ + + /* Check if we are able to advance to the next selection block */ + if((status1=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter1))<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block"); + if((status2=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter2))<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block"); + + /* Did we run out of blocks at the same time? */ + if(status1==FALSE && status2==FALSE) + break; + else if(status1!=status2) { + HGOTO_DONE(FALSE); + } /* end if */ + else { + /* Advance to next block in selection iterators */ + if(H5S_SELECT_ITER_NEXT_BLOCK(&iter1)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block"); + if(H5S_SELECT_ITER_NEXT_BLOCK(&iter2)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block"); + } /* end else */ + } /* end while */ + } /* end else */ } /* end else */ done: @@ -1404,7 +1412,7 @@ done: HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_shape_same() */ diff --git a/test/tselect.c b/test/tselect.c index fd577ca..3f18eb9 100644 --- a/test/tselect.c +++ b/test/tselect.c @@ -5672,7 +5672,7 @@ test_scalar_select(void) /**************************************************************** ** ** test_scalar_select2(): Tests selections on scalar dataspace, -** verify H5Shyperslab and H5Sselect_elements fails for +** verify H5Sselect_hyperslab and H5Sselect_elements fails for ** scalar dataspace. ** ****************************************************************/ @@ -5722,6 +5722,146 @@ test_scalar_select2(void) /**************************************************************** ** +** test_scalar_select3(): Test basic H5S (dataspace) selection code. +** Tests selections on scalar dataspaces in memory +** +****************************************************************/ +static void +test_scalar_select3(void) +{ + hid_t fid1; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + hid_t sid1,sid2; /* Dataspace ID */ + hsize_t dims2[] = {SPACE7_DIM1, SPACE7_DIM2}; + hsize_t coord1[SPACE7_RANK]; /* Coordinates for point selection */ + hsize_t start[SPACE7_RANK]; /* Hyperslab start */ + hsize_t count[SPACE7_RANK]; /* Hyperslab block count */ + uint8_t wval_uint8, /* Value written out */ + rval_uint8; /* Value read in */ + unsigned short wval_ushort, /* Another value written out */ + rval_ushort; /* Another value read in */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing I/O on Selections in Scalar Dataspaces in Memory\n")); + + /* Create file */ + fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid1, FAIL, "H5Fcreate"); + + /* Create dataspace for dataset */ + sid1 = H5Screate_simple(SPACE7_RANK, dims2, NULL); + CHECK(sid1, FAIL, "H5Screate_simple"); + + /* Create dataspace for writing buffer */ + sid2 = H5Screate(H5S_SCALAR); + CHECK(sid2, FAIL, "H5Screate_simple"); + + /* Create a dataset */ + dataset = H5Dcreate2(fid1, "Dataset1", H5T_NATIVE_UCHAR, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + CHECK(dataset, FAIL, "H5Dcreate2"); + + /* Select one element in file with a point selection */ + coord1[0] = 0; coord1[1] = 2; + ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)1, (const hsize_t **)&coord1); + CHECK(ret, FAIL, "H5Sselect_elements"); + + /* Write single point to disk */ + wval_uint8 = 12; + ret = H5Dwrite(dataset, H5T_NATIVE_UCHAR, sid2, sid1, H5P_DEFAULT, &wval_uint8); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Read scalar element from disk */ + rval_uint8 = 0; + ret = H5Dread(dataset, H5T_NATIVE_UCHAR, sid2, sid1, H5P_DEFAULT, &rval_uint8); + CHECK(ret, FAIL, "H5Dread"); + + /* Check value read back in */ + if(rval_uint8 != wval_uint8) + TestErrPrintf("%u: Error! rval=%u, should be: wval=%u\n", (unsigned)__LINE__, (unsigned)rval_uint8, (unsigned)wval_uint8); + + /* Write single point to disk (with a datatype conversion) */ + wval_ushort = 23; + ret = H5Dwrite(dataset, H5T_NATIVE_USHORT, sid2, sid1, H5P_DEFAULT, &wval_ushort); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Read scalar element from disk */ + rval_ushort = 0; + ret = H5Dread(dataset, H5T_NATIVE_USHORT, sid2, sid1, H5P_DEFAULT, &rval_ushort); + CHECK(ret, FAIL, "H5Dread"); + + /* Check value read back in */ + if(rval_ushort != wval_ushort) + TestErrPrintf("%u: Error! rval=%u, should be: wval=%u\n", (unsigned)__LINE__, (unsigned)rval_ushort, (unsigned)wval_ushort); + + /* Select one element in file with a hyperslab selection */ + start[0] = 4; start[1] = 3; + count[0] = 1; count[1] = 1; + ret = H5Sselect_hyperslab(sid1, H5S_SELECT_SET, start, NULL, count, NULL); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Write single hyperslab element to disk */ + wval_uint8 = 92; + ret = H5Dwrite(dataset, H5T_NATIVE_UCHAR, sid2, sid1, H5P_DEFAULT, &wval_uint8); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Read scalar element from disk */ + rval_uint8 = 0; + ret = H5Dread(dataset, H5T_NATIVE_UCHAR, sid2, sid1, H5P_DEFAULT, &rval_uint8); + CHECK(ret, FAIL, "H5Dread"); + + /* Check value read back in */ + if(rval_uint8 != wval_uint8) + TestErrPrintf("%u: Error! rval=%u, should be: wval=%u\n", (unsigned)__LINE__, (unsigned)rval_uint8, (unsigned)wval_uint8); + + /* Write single hyperslab element to disk (with a datatype conversion) */ + wval_ushort = 107; + ret = H5Dwrite(dataset, H5T_NATIVE_USHORT, sid2, sid1, H5P_DEFAULT, &wval_ushort); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Read scalar element from disk */ + rval_ushort = 0; + ret = H5Dread(dataset, H5T_NATIVE_USHORT, sid2, sid1, H5P_DEFAULT, &rval_ushort); + CHECK(ret, FAIL, "H5Dread"); + + /* Check value read back in */ + if(rval_ushort != wval_ushort) + TestErrPrintf("%u: Error! rval=%u, should be: wval=%u\n", (unsigned)__LINE__, (unsigned)rval_ushort, (unsigned)wval_ushort); + + /* Select no elements in memory & file with "none" selections */ + ret = H5Sselect_none(sid1); + CHECK(ret, FAIL, "H5Sselect_none"); + + ret = H5Sselect_none(sid2); + CHECK(ret, FAIL, "H5Sselect_none"); + + /* Write no data to disk */ + ret = H5Dwrite(dataset, H5T_NATIVE_UCHAR, sid2, sid1, H5P_DEFAULT, &wval_uint8); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Write no data to disk (with a datatype conversion) */ + ret = H5Dwrite(dataset, H5T_NATIVE_USHORT, sid2, sid1, H5P_DEFAULT, &wval_ushort); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Close memory dataspace */ + ret = H5Sclose(sid2); + CHECK(ret, FAIL, "H5Sclose"); + + /* Close disk dataspace */ + ret = H5Sclose(sid1); + CHECK(ret, FAIL, "H5Sclose"); + + /* Close Dataset */ + ret = H5Dclose(dataset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Close file */ + ret = H5Fclose(fid1); + CHECK(ret, FAIL, "H5Fclose"); +} /* test_scalar_select3() */ + +/**************************************************************** +** ** test_shape_same(): Tests selections on dataspace, verify that ** "shape same" routine is working correctly. ** @@ -5744,6 +5884,8 @@ test_shape_same(void) hid_t regular_hyper_sid; /* Dataspace ID with regular hyperslab selection */ hid_t irreg_hyper_sid; /* Dataspace ID with irregular hyperslab selection */ hid_t none_hyper_sid; /* Dataspace ID with "no hyperslabs" selection */ + hid_t scalar_all_sid; /* ID for scalar dataspace with "all" selection */ + hid_t scalar_none_sid; /* ID for scalar dataspace with "none" selection */ hid_t tmp_sid; /* Temporary dataspace ID */ hsize_t dims[] = {SPACE9_DIM1, SPACE9_DIM2}; hsize_t coord1[1][SPACE2_RANK]; /* Coordinates for single point selection */ @@ -5885,6 +6027,18 @@ test_shape_same(void) ret = H5Sselect_hyperslab(none_hyper_sid,H5S_SELECT_XOR,start,stride,count,block); CHECK(ret, FAIL, "H5Sselect_hyperslab"); + /* Create scalar dataspace for "all" selection */ + scalar_all_sid = H5Screate(H5S_SCALAR); + CHECK(scalar_all_sid, FAIL, "H5Screate"); + + /* Create scalar dataspace for "none" selection */ + scalar_none_sid = H5Screate(H5S_SCALAR); + CHECK(scalar_none_sid, FAIL, "H5Screate"); + + /* Un-Select entire extent for dataspace */ + ret = H5Sselect_none(scalar_none_sid); + CHECK(ret, FAIL, "H5Sselect_none"); + /* Compare "all" selection to all the selections created */ /* Compare against itself */ check=H5S_select_shape_same_test(all_sid,all_sid); @@ -5936,6 +6090,14 @@ test_shape_same(void) check=H5S_select_shape_same_test(all_sid,none_hyper_sid); VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(all_sid, scalar_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(all_sid, scalar_none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare "none" selection to all the selections created */ /* Compare against itself */ check=H5S_select_shape_same_test(none_sid,none_sid); @@ -5987,6 +6149,14 @@ test_shape_same(void) check=H5S_select_shape_same_test(none_sid,none_hyper_sid); VERIFY(check, TRUE, "H5S_select_shape_same_test"); + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(none_sid, scalar_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(none_sid, scalar_none_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + /* Compare single point selection to all the selections created */ /* Compare against itself */ check=H5S_select_shape_same_test(single_pt_sid,single_pt_sid); @@ -6038,6 +6208,14 @@ test_shape_same(void) check=H5S_select_shape_same_test(single_pt_sid,none_hyper_sid); VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(single_pt_sid, scalar_all_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(single_pt_sid, scalar_none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare multiple point selection to all the selections created */ /* Compare against itself */ check=H5S_select_shape_same_test(mult_pt_sid,mult_pt_sid); @@ -6089,6 +6267,14 @@ test_shape_same(void) check=H5S_select_shape_same_test(mult_pt_sid,none_hyper_sid); VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(mult_pt_sid, scalar_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(mult_pt_sid, scalar_none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare single "normal" hyperslab selection to all the selections created */ /* Compare against itself */ check=H5S_select_shape_same_test(single_hyper_sid,single_hyper_sid); @@ -6195,6 +6381,14 @@ test_shape_same(void) ret = H5Sclose(tmp_sid); CHECK(ret, FAIL, "H5Sclose"); + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(single_hyper_sid, scalar_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(single_hyper_sid, scalar_none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare single "all" hyperslab selection to all the selections created */ /* Compare against itself */ check=H5S_select_shape_same_test(single_hyper_all_sid,single_hyper_all_sid); @@ -6301,6 +6495,14 @@ test_shape_same(void) ret = H5Sclose(tmp_sid); CHECK(ret, FAIL, "H5Sclose"); + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(single_hyper_all_sid, scalar_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(single_hyper_all_sid, scalar_none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare single "point" hyperslab selection to all the selections created */ /* Compare against itself */ check=H5S_select_shape_same_test(single_hyper_pt_sid,single_hyper_pt_sid); @@ -6352,6 +6554,14 @@ test_shape_same(void) check=H5S_select_shape_same_test(single_hyper_pt_sid,none_hyper_sid); VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(single_hyper_pt_sid, scalar_all_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(single_hyper_pt_sid, scalar_none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare regular, strided hyperslab selection to all the selections created */ /* Compare against itself */ check=H5S_select_shape_same_test(regular_hyper_sid,regular_hyper_sid); @@ -6470,6 +6680,14 @@ test_shape_same(void) ret = H5Sclose(tmp_sid); CHECK(ret, FAIL, "H5Sclose"); + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(regular_hyper_sid, scalar_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(regular_hyper_sid, scalar_none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Compare irregular hyperslab selection to all the selections created */ /* Compare against itself */ check=H5S_select_shape_same_test(irreg_hyper_sid,irreg_hyper_sid); @@ -6550,6 +6768,136 @@ test_shape_same(void) ret = H5Sclose(tmp_sid); CHECK(ret, FAIL, "H5Sclose"); + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(irreg_hyper_sid, scalar_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(irreg_hyper_sid, scalar_none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Compare scalar "all" dataspace with all selections created */ + + /* Compare against itself */ + check = H5S_select_shape_same_test(scalar_all_sid, scalar_all_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against copy of itself */ + tmp_sid = H5Scopy(scalar_all_sid); + CHECK(tmp_sid, FAIL, "H5Scopy"); + + check = H5S_select_shape_same_test(scalar_all_sid, tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Compare against "all" selection */ + check = H5S_select_shape_same_test(scalar_all_sid, all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "none" selection */ + check = H5S_select_shape_same_test(scalar_all_sid, none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against single point selection */ + check = H5S_select_shape_same_test(scalar_all_sid, single_pt_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against multiple point selection */ + check = H5S_select_shape_same_test(scalar_all_sid, mult_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "plain" single hyperslab selection */ + check = H5S_select_shape_same_test(scalar_all_sid, single_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "all" single hyperslab selection */ + check = H5S_select_shape_same_test(scalar_all_sid, single_hyper_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "single point" single hyperslab selection */ + check = H5S_select_shape_same_test(scalar_all_sid, single_hyper_pt_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against regular, strided hyperslab selection */ + check = H5S_select_shape_same_test(scalar_all_sid, regular_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against irregular hyperslab selection */ + check = H5S_select_shape_same_test(scalar_all_sid, irreg_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "no" hyperslab selection */ + check = H5S_select_shape_same_test(scalar_all_sid, none_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against scalar "none" hyperslab selection */ + check = H5S_select_shape_same_test(scalar_all_sid, scalar_none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Compare scalar "none" dataspace with all selections created */ + + /* Compare against itself */ + check = H5S_select_shape_same_test(scalar_none_sid, scalar_none_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against copy of itself */ + tmp_sid = H5Scopy(scalar_none_sid); + CHECK(tmp_sid, FAIL, "H5Scopy"); + + check = H5S_select_shape_same_test(scalar_none_sid, tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Compare against "all" selection */ + check = H5S_select_shape_same_test(scalar_none_sid, all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "none" selection */ + check = H5S_select_shape_same_test(scalar_none_sid, none_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against single point selection */ + check = H5S_select_shape_same_test(scalar_none_sid, single_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against multiple point selection */ + check = H5S_select_shape_same_test(scalar_none_sid, mult_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "plain" single hyperslab selection */ + check = H5S_select_shape_same_test(scalar_none_sid, single_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "all" single hyperslab selection */ + check = H5S_select_shape_same_test(scalar_none_sid, single_hyper_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "single point" single hyperslab selection */ + check = H5S_select_shape_same_test(scalar_none_sid, single_hyper_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against regular, strided hyperslab selection */ + check = H5S_select_shape_same_test(scalar_none_sid, regular_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against irregular hyperslab selection */ + check = H5S_select_shape_same_test(scalar_none_sid, irreg_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "no" hyperslab selection */ + check = H5S_select_shape_same_test(scalar_none_sid, none_hyper_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against scalar "all" hyperslab selection */ + check = H5S_select_shape_same_test(scalar_none_sid, scalar_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + /* Close dataspaces */ ret = H5Sclose(all_sid); @@ -6572,6 +6920,10 @@ test_shape_same(void) CHECK(ret, FAIL, "H5Sclose"); ret = H5Sclose(none_hyper_sid); CHECK(ret, FAIL, "H5Sclose"); + ret = H5Sclose(scalar_all_sid); + CHECK(ret, FAIL, "H5Sclose"); + ret = H5Sclose(scalar_none_sid); + CHECK(ret, FAIL, "H5Sclose"); } /* test_shape_same() */ @@ -7886,6 +8238,7 @@ test_select(void) /* Test selections on scalar dataspaces */ test_scalar_select(); test_scalar_select2(); + test_scalar_select3(); /* Test "same shape" routine */ test_shape_same(); -- cgit v0.12