hdf5/test/hyperslab.c
Dana Robinson 7f1e49206d
Renamed COPYING to LICENSE (#4978)
This is where most people will expect to find license information. The
COPYING_LBNL_HDF5 file has also been renamed to LICENSE_LBNL_HDF5.
The licenses are unchanged.
2024-10-18 21:13:04 -07:00

1362 lines
49 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Purpose: Hyperslab operations are rather complex, so this file
* attempts to test them extensively so we can be relatively
* sure they really work. We only test 1d, 2d, and 3d cases
* because testing general dimensionalities would require us to
* rewrite much of the hyperslab stuff.
*/
#include "h5test.h"
#include "H5VMprivate.h"
#define TEST_SMALL 0x0001
#define TEST_MEDIUM 0x0002
#define VARIABLE_SRC 0
#define VARIABLE_DST 1
#define VARIABLE_BOTH 2
#define ARRAY_FILL_SIZE 4
#define ARRAY_OFFSET_NDIMS 3
/*-------------------------------------------------------------------------
* Function: init_full
*
* Purpose: Initialize full array.
*
* Return: void
*
*-------------------------------------------------------------------------
*/
static unsigned
init_full(uint8_t *array, size_t nx, size_t ny, size_t nz)
{
uint8_t acc = 128;
unsigned total = 0;
size_t i, j, k;
for (i = 0; i < nx; i++)
for (j = 0; j < ny; j++)
for (k = 0; k < nz; k++) {
total += acc;
*array = acc;
acc++;
array++;
} /* end for */
return total;
} /* end init_full() */
/*-------------------------------------------------------------------------
* Function: print_array
*
* Purpose: Prints the values in an array
*
* Return: void
*
*-------------------------------------------------------------------------
*/
static void
print_array(uint8_t *array, size_t nx, size_t ny, size_t nz)
{
size_t i, j, k;
for (i = 0; i < nx; i++) {
if (nz > 1)
printf("i=%lu:\n", (unsigned long)i);
else
printf("%03lu:", (unsigned long)i);
for (j = 0; j < ny; j++) {
if (nz > 1)
printf("%03lu:", (unsigned long)j);
for (k = 0; k < nz; k++)
printf(" %3d", *array++);
if (nz > 1)
printf("\n");
} /* end for */
printf("\n");
} /* end for */
} /* end print_array() */
/*-------------------------------------------------------------------------
* Function: print_ref
*
* Purpose: Prints the reference value
*
* Return: Success: 0
*
* Failure:
*
*-------------------------------------------------------------------------
*/
static void
print_ref(size_t nx, size_t ny, size_t nz)
{
uint8_t *array;
if (NULL != (array = (uint8_t *)malloc(nx * ny * nz))) {
printf("Reference array:\n");
init_full(array, nx, ny, nz);
print_array(array, nx, ny, nz);
free(array);
}
} /* end print_ref() */
/*-------------------------------------------------------------------------
* Function: test_fill
*
* Purpose: Tests the H5VM_hyper_fill() function.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_fill(size_t nx, size_t ny, size_t nz, size_t di, size_t dj, size_t dk, size_t ddx, size_t ddy,
size_t ddz)
{
uint8_t *dst = NULL; /*destination array */
hsize_t hs_size[3]; /*hyperslab size */
hsize_t dst_size[3]; /*destination total size */
hsize_t dst_offset[3]; /*offset of hyperslab in dest */
unsigned ref_value; /*reference value */
unsigned acc; /*accumulator */
size_t i, j, k, dx, dy, dz; /*counters */
size_t u, v, w;
unsigned ndims; /*hyperslab dimensionality */
char dim[64], s[256]; /*temp string */
unsigned fill_value; /*fill value */
/*
* Dimensionality.
*/
if (0 == nz) {
if (0 == ny) {
ndims = 1;
ny = nz = 1;
snprintf(dim, sizeof(dim), "%lu", (unsigned long)nx);
} /* end if */
else {
ndims = 2;
nz = 1;
snprintf(dim, sizeof(dim), "%lux%lu", (unsigned long)nx, (unsigned long)ny);
} /* end else */
} /* end if */
else {
ndims = 3;
snprintf(dim, sizeof(dim), "%lux%lux%lu", (unsigned long)nx, (unsigned long)ny, (unsigned long)nz);
} /* end else */
snprintf(s, sizeof(s), "Testing hyperslab fill %-11s variable hyperslab", dim);
printf("%-70s", s);
fflush(stdout);
/* Allocate array */
if (NULL == (dst = (uint8_t *)calloc((size_t)1, nx * ny * nz)))
TEST_ERROR;
init_full(dst, nx, ny, nz);
for (i = 0; i < nx; i += di) {
for (j = 0; j < ny; j += dj) {
for (k = 0; k < nz; k += dk) {
for (dx = 1; dx <= nx - i; dx += ddx) {
for (dy = 1; dy <= ny - j; dy += ddy) {
for (dz = 1; dz <= nz - k; dz += ddz) {
/* Describe the hyperslab */
dst_size[0] = nx;
dst_size[1] = ny;
dst_size[2] = nz;
dst_offset[0] = i;
dst_offset[1] = j;
dst_offset[2] = k;
hs_size[0] = dx;
hs_size[1] = dy;
hs_size[2] = dz;
for (fill_value = 0; fill_value < 256; fill_value += 64) {
/*
* Initialize the full array, then subtract the
* original * fill values and add the new ones.
*/
ref_value = init_full(dst, nx, ny, nz);
for (u = (size_t)dst_offset[0]; u < dst_offset[0] + dx; u++)
for (v = (size_t)dst_offset[1]; v < dst_offset[1] + dy; v++)
for (w = (size_t)dst_offset[2]; w < dst_offset[2] + dz; w++)
ref_value -= dst[u * ny * nz + v * nz + w];
ref_value += fill_value * (unsigned)dx * (unsigned)dy * (unsigned)dz;
/* Fill the hyperslab with some value */
H5VM_hyper_fill(ndims, hs_size, dst_size, dst_offset, dst, fill_value);
/*
* Sum the array and compare it to the
* reference value.
*/
acc = 0;
for (u = 0; u < nx; u++)
for (v = 0; v < ny; v++)
for (w = 0; w < nz; w++)
acc += dst[u * ny * nz + v * nz + w];
if (acc != ref_value) {
H5_FAILED();
if (!HDisatty(1)) {
/*
* Print debugging info unless output
* is going directly to a terminal.
*/
AT();
printf(" acc != ref_value\n");
printf(" i=%lu, j=%lu, k=%lu, "
"dx=%lu, dy=%lu, dz=%lu, "
"fill=%d\n",
(unsigned long)i, (unsigned long)j, (unsigned long)k,
(unsigned long)dx, (unsigned long)dy, (unsigned long)dz,
fill_value);
print_ref(nx, ny, nz);
printf("\n Result is:\n");
print_array(dst, nx, ny, nz);
} /* end if */
goto error;
} /* end if */
} /* end for */
} /* end for */
} /* end for */
} /* end for */
} /* end for */
} /* end for */
} /* end for */
PASSED();
free(dst);
return SUCCEED;
error:
if (dst)
free(dst);
return FAIL;
} /* end test_fill() */
/*-------------------------------------------------------------------------
* Function: test_copy
*
* Purpose: Tests H5VM_hyper_copy().
*
* The NX, NY, and NZ arguments are the size for the source and
* destination arrays. You may pass zero for NZ or for NY and
* NZ to test the 2-d and 1-d cases respectively.
*
* A hyperslab is copied from/to (depending on MODE) various
* places in SRC and DST beginning at 0,0,0 and increasing
* location by DI,DJ,DK in the x, y, and z directions.
*
* For each hyperslab location, various sizes of hyperslabs are
* tried beginning with 1x1x1 and increasing the size in each
* dimension by DDX,DDY,DDZ.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_copy(int mode, size_t nx, size_t ny, size_t nz, size_t di, size_t dj, size_t dk, size_t ddx, size_t ddy,
size_t ddz)
{
uint8_t *src = NULL; /*source array */
uint8_t *dst = NULL; /*destination array */
hsize_t hs_size[3]; /*hyperslab size */
hsize_t dst_size[3]; /*destination total size */
hsize_t src_size[3]; /*source total size */
hsize_t dst_offset[3]; /*offset of hyperslab in dest */
hsize_t src_offset[3]; /*offset of hyperslab in source */
unsigned ref_value; /*reference value */
unsigned acc; /*accumulator */
hsize_t i, j, k, dx, dy, dz; /*counters */
hsize_t u, v, w;
unsigned ndims; /*hyperslab dimensionality */
char dim[64], s[256]; /*temp string */
const char *sub;
/*
* Dimensionality.
*/
if (0 == nz) {
if (0 == ny) {
ndims = 1;
ny = nz = 1;
snprintf(dim, sizeof(dim), "%lu", (unsigned long)nx);
} /* end if */
else {
ndims = 2;
nz = 1;
snprintf(dim, sizeof(dim), "%lux%lu", (unsigned long)nx, (unsigned long)ny);
} /* end else */
} /* end if */
else {
ndims = 3;
snprintf(dim, sizeof(dim), "%lux%lux%lu", (unsigned long)nx, (unsigned long)ny, (unsigned long)nz);
} /* end else */
switch (mode) {
case VARIABLE_SRC:
/*
* The hyperslab "travels" through the source array but the
* destination hyperslab is always at the origin of the destination
* array.
*/
sub = "variable source";
break;
case VARIABLE_DST:
/*
* We always read a hyperslab from the origin of the source and copy it
* to a hyperslab at various locations in the destination.
*/
sub = "variable destination";
break;
case VARIABLE_BOTH:
/*
* We read the hyperslab from various locations in the source and copy
* it to the same location in the destination.
*/
sub = "sync source & dest ";
break;
default:
FAIL_PUTS_ERROR("Unhandled case");
} /* end switch */
snprintf(s, sizeof(s), "Testing hyperslab copy %-11s %s", dim, sub);
printf("%-70s", s);
fflush(stdout);
/*
* Allocate arrays
*/
if (NULL == (src = (uint8_t *)calloc((size_t)1, nx * ny * nz)))
TEST_ERROR;
if (NULL == (dst = (uint8_t *)calloc((size_t)1, nx * ny * nz)))
TEST_ERROR;
init_full(src, nx, ny, nz);
for (i = 0; i < nx; i += di) {
for (j = 0; j < ny; j += dj) {
for (k = 0; k < nz; k += dk) {
for (dx = 1; dx <= nx - i; dx += ddx) {
for (dy = 1; dy <= ny - j; dy += ddy) {
for (dz = 1; dz <= nz - k; dz += ddz) {
/*
* Describe the source and destination hyperslabs
* and the arrays to which they belong.
*/
hs_size[0] = dx;
hs_size[1] = dy;
hs_size[2] = dz;
dst_size[0] = src_size[0] = nx;
dst_size[1] = src_size[1] = ny;
dst_size[2] = src_size[2] = nz;
switch (mode) {
case VARIABLE_SRC:
dst_offset[0] = 0;
dst_offset[1] = 0;
dst_offset[2] = 0;
src_offset[0] = i;
src_offset[1] = j;
src_offset[2] = k;
break;
case VARIABLE_DST:
dst_offset[0] = i;
dst_offset[1] = j;
dst_offset[2] = k;
src_offset[0] = 0;
src_offset[1] = 0;
src_offset[2] = 0;
break;
case VARIABLE_BOTH:
dst_offset[0] = i;
dst_offset[1] = j;
dst_offset[2] = k;
src_offset[0] = i;
src_offset[1] = j;
src_offset[2] = k;
break;
default:
FAIL_PUTS_ERROR("Unhandled case");
} /* end switch */
/*
* Sum the main array directly to get a reference
* value to compare against later.
*/
ref_value = 0;
for (u = src_offset[0]; u < src_offset[0] + dx; u++)
for (v = src_offset[1]; v < src_offset[1] + dy; v++)
for (w = src_offset[2]; w < src_offset[2] + dz; w++)
ref_value += src[u * ny * nz + v * nz + w];
/*
* Set all loc values to 1 so we can detect writing
* outside the hyperslab.
*/
for (u = 0; u < nx; u++)
for (v = 0; v < ny; v++)
for (w = 0; w < nz; w++)
dst[u * ny * nz + v * nz + w] = 1;
/*
* Copy a hyperslab from the global array to the
* local array.
*/
H5VM_hyper_copy(ndims, hs_size, dst_size, dst_offset, dst, src_size, src_offset,
src);
/*
* Sum the destination hyperslab. It should be
* the same as the reference value.
*/
acc = 0;
for (u = dst_offset[0]; u < dst_offset[0] + dx; u++)
for (v = dst_offset[1]; v < dst_offset[1] + dy; v++)
for (w = dst_offset[2]; w < dst_offset[2] + dz; w++)
acc += dst[u * ny * nz + v * nz + w];
if (acc != ref_value) {
H5_FAILED();
if (!HDisatty(1)) {
/*
* Print debugging info unless output is
* going directly to a terminal.
*/
AT();
printf(" acc != ref_value\n");
printf(" i=%lu, j=%lu, k=%lu, "
"dx=%lu, dy=%lu, dz=%lu\n",
(unsigned long)i, (unsigned long)j, (unsigned long)k,
(unsigned long)dx, (unsigned long)dy, (unsigned long)dz);
print_ref(nx, ny, nz);
printf("\n Destination array is:\n");
print_array(dst, nx, ny, nz);
} /* end if */
goto error;
} /* end if */
/*
* Sum the entire array. It should be a fixed
* amount larger than the reference value since
* we added the border of 1's to the hyperslab.
*/
acc = 0;
for (u = 0; u < nx; u++)
for (v = 0; v < ny; v++)
for (w = 0; w < nz; w++)
acc += dst[u * ny * nz + v * nz + w];
/*
* The following casts are to work around an
* optimization bug in the Mongoose 7.20 Irix64
* compiler.
*/
if (acc + (unsigned)dx * (unsigned)dy * (unsigned)dz !=
ref_value + nx * ny * nz) {
H5_FAILED();
if (!HDisatty(1)) {
/*
* Print debugging info unless output is
* going directly to a terminal.
*/
AT();
printf(" acc != ref_value + nx*ny*nz - "
"dx*dy*dz\n");
printf(" i=%lu, j=%lu, k=%lu, "
"dx=%lu, dy=%lu, dz=%lu\n",
(unsigned long)i, (unsigned long)j, (unsigned long)k,
(unsigned long)dx, (unsigned long)dy, (unsigned long)dz);
print_ref(nx, ny, nz);
printf("\n Destination array is:\n");
print_array(dst, nx, ny, nz);
} /* end if */
goto error;
} /* end if */
} /* end for */
} /* end for */
} /* end for */
} /* end for */
} /* end for */
} /* end for */
PASSED();
free(src);
free(dst);
return SUCCEED;
error:
if (src)
free(src);
if (dst)
free(dst);
return FAIL;
} /* end test_copy() */
/*-------------------------------------------------------------------------
* Function: test_multifill
*
* Purpose: Tests the H5VM_stride_copy() function by using it to fill a
* hyperslab by replicating a multi-byte sequence. This might
* be useful to initialize an array of structs with a default
* struct value, or to initialize an array of floating-point
* values with a default bit-pattern.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_multifill(size_t nx)
{
hsize_t size;
hsize_t src_stride;
hsize_t dst_stride;
char s[64];
struct a_struct {
int left;
double mid;
int right;
} fill, *src = NULL, *dst = NULL;
hsize_t i, j;
printf("%-70s", "Testing multi-byte fill value");
fflush(stdout);
/* Initialize the source and destination */
if (NULL == (src = (struct a_struct *)malloc(nx * sizeof(*src))))
TEST_ERROR;
if (NULL == (dst = (struct a_struct *)malloc(nx * sizeof(*dst))))
TEST_ERROR;
for (i = 0; i < nx; i++) {
src[i].left = 1111111;
src[i].mid = 12345.6789;
src[i].right = 2222222;
dst[i].left = 3333333;
dst[i].mid = 98765.4321;
dst[i].right = 4444444;
} /* end for */
/*
* Describe the fill value. The zero stride says to read the same thing
* over and over again.
*/
fill.left = 55555555;
fill.mid = 3.1415927;
fill.right = 66666666;
src_stride = 0;
/*
* The destination stride says to fill in one value per array element
*/
dst_stride = sizeof(fill);
/*
* Copy the fill value into each element
*/
size = nx;
H5VM_stride_copy(1, (hsize_t)sizeof(double), &size, &dst_stride, &(dst[0].mid), &src_stride, &(fill.mid));
/*
* Check
*/
s[0] = '\0';
for (i = 0; i < nx; i++) {
if (dst[i].left != 3333333)
snprintf(s, sizeof(s), "bad dst[%lu].left", (unsigned long)i);
else if (!H5_DBL_ABS_EQUAL(dst[i].mid, fill.mid))
/* Check if two DOUBLE values are equal. If their difference
* is smaller than the EPSILON value for double, they are
* considered equal. See the definition in h5test.h.
*/
snprintf(s, sizeof(s), "bad dst[%lu].mid", (unsigned long)i);
else if (dst[i].right != 4444444)
snprintf(s, sizeof(s), "bad dst[%lu].right", (unsigned long)i);
if (s[0]) {
H5_FAILED();
if (!HDisatty(1)) {
AT();
printf(" fill={%d,%g,%d}\n ", fill.left, fill.mid, fill.right);
for (j = 0; j < sizeof(fill); j++)
printf(" %02x", ((uint8_t *)&fill)[j]);
printf("\n dst[%lu]={%d,%g,%d}\n ", (unsigned long)i, dst[i].left, dst[i].mid,
dst[i].right);
for (j = 0; j < sizeof(dst[i]); j++)
printf(" %02x", ((uint8_t *)(dst + i))[j]);
printf("\n");
} /* end if */
goto error;
} /* end if */
} /* end for */
PASSED();
free(src);
free(dst);
return SUCCEED;
error:
if (src)
free(src);
if (dst)
free(dst);
return FAIL;
} /* end test_multifill() */
/*-------------------------------------------------------------------------
* Function: test_endian
*
* Purpose: Tests the H5VM_stride_copy() function by using it to copy an
* array of integers and swap the byte ordering from little
* endian to big endian or vice versa depending on the hardware.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_endian(size_t nx)
{
uint8_t *src = NULL; /*source array */
uint8_t *dst = NULL; /*destination array */
hssize_t src_stride[2]; /*source strides */
hssize_t dst_stride[2]; /*destination strides */
hsize_t size[2]; /*size vector */
hsize_t i, j;
printf("%-70s", "Testing endian conversion by stride");
fflush(stdout);
/* Initialize arrays */
if (NULL == (src = (uint8_t *)malloc(nx * 4)))
TEST_ERROR;
if (NULL == (dst = (uint8_t *)calloc(nx, (size_t)4)))
TEST_ERROR;
init_full(src, nx, (size_t)4, (size_t)1);
/* Initialize strides */
src_stride[0] = 0;
src_stride[1] = 1;
dst_stride[0] = 8;
dst_stride[1] = -1;
size[0] = nx;
size[1] = 4;
/* Copy the array */
H5VM_stride_copy_s(2, (hsize_t)1, size, dst_stride, dst + 3, src_stride, src);
/* Compare */
for (i = 0; i < nx; i++) {
for (j = 0; j < 4; j++) {
if (src[i * 4 + j] != dst[i * 4 + 3 - j]) {
H5_FAILED();
if (!HDisatty(1)) {
/*
* Print debugging info unless output is going directly
* to a terminal.
*/
AT();
printf(" i=%lu, j=%lu\n", (unsigned long)i, (unsigned long)j);
printf(" Source array is:\n");
print_array(src, nx, (size_t)4, (size_t)1);
printf("\n Result is:\n");
print_array(dst, nx, (size_t)4, (size_t)1);
} /* end if */
goto error;
} /* end if */
} /* end for */
} /* end for */
PASSED();
free(src);
free(dst);
return SUCCEED;
error:
if (src)
free(src);
if (dst)
free(dst);
return FAIL;
} /* end test_endian() */
/*-------------------------------------------------------------------------
* Function: test_transpose
*
* Purpose: Copy a 2d array from here to there and transpose the elements
* as it's copied.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_transpose(size_t nx, size_t ny)
{
int *src = NULL;
int *dst = NULL;
hsize_t src_stride[2], dst_stride[2];
hsize_t size[2];
char s[256];
hsize_t i, j;
snprintf(s, sizeof(s), "Testing 2d transpose by stride %4lux%-lud", (unsigned long)nx, (unsigned long)ny);
printf("%-70s", s);
fflush(stdout);
/* Initialize */
if (NULL == (src = (int *)malloc(nx * ny * sizeof(*src))))
TEST_ERROR;
if (NULL == (dst = (int *)calloc(nx * ny, sizeof(*dst))))
TEST_ERROR;
for (i = 0; i < nx; i++)
for (j = 0; j < ny; j++)
src[i * ny + j] = (int)(i * ny + j);
/* Build stride info */
size[0] = nx;
size[1] = ny;
src_stride[0] = 0;
src_stride[1] = sizeof(*src);
dst_stride[0] = (hsize_t)((1 - nx * ny) * sizeof(*src));
dst_stride[1] = (hsize_t)(nx * sizeof(*src));
/* Copy and transpose */
H5VM_stride_copy(2, (hsize_t)sizeof(*src), size, dst_stride, dst, src_stride, src);
/* Check */
for (i = 0; i < nx; i++) {
for (j = 0; j < ny; j++) {
if (src[i * ny + j] != dst[j * nx + i]) {
H5_FAILED();
if (!HDisatty(1)) {
AT();
printf(" diff at i=%lu, j=%lu\n", (unsigned long)i, (unsigned long)j);
printf(" Source is:\n");
for (i = 0; i < nx; i++) {
printf("%3lu:", (unsigned long)i);
for (j = 0; j < ny; j++)
printf(" %6d", src[i * ny + j]);
printf("\n");
} /* end for */
printf("\n Destination is:\n");
for (i = 0; i < ny; i++) {
printf("%3lu:", (unsigned long)i);
for (j = 0; j < nx; j++)
printf(" %6d", dst[i * nx + j]);
printf("\n");
} /* end for */
} /* end if */
goto error;
} /* end if */
} /* end for */
} /* end for */
PASSED();
free(src);
free(dst);
return SUCCEED;
error:
if (src)
free(src);
if (dst)
free(dst);
return FAIL;
} /* end test_transpose() */
/*-------------------------------------------------------------------------
* Function: test_sub_super
*
* Purpose: Tests H5VM_stride_copy() to reduce the resolution of an image
* by copying half the pixels in the X and Y directions. Then
* we use the small image and duplicate every pixel to result in
* a 2x2 square.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_sub_super(size_t nx, size_t ny)
{
uint8_t *full = NULL; /*original image */
uint8_t *half = NULL; /*image at 1/2 resolution */
uint8_t *twice = NULL; /*2x2 pixels */
hsize_t src_stride[4]; /*source stride info */
hsize_t dst_stride[4]; /*destination stride info */
hsize_t size[4]; /*number of sample points */
hsize_t i, j;
char s[256];
snprintf(s, sizeof(s), "Testing image sampling %4lux%-4lu to %4lux%-4lu ", (unsigned long)(2 * nx),
(unsigned long)(2 * ny), (unsigned long)nx, (unsigned long)ny);
printf("%-70s", s);
fflush(stdout);
/* Initialize */
if (NULL == (full = (uint8_t *)malloc(4 * nx * ny)))
TEST_ERROR;
if (NULL == (half = (uint8_t *)calloc((size_t)1, nx * ny)))
TEST_ERROR;
if (NULL == (twice = (uint8_t *)calloc((size_t)4, nx * ny)))
TEST_ERROR;
init_full(full, 2 * nx, 2 * ny, (size_t)1);
/* Setup */
size[0] = nx;
size[1] = ny;
src_stride[0] = (hsize_t)(2 * ny);
src_stride[1] = 2;
dst_stride[0] = 0;
dst_stride[1] = 1;
/* Copy */
H5VM_stride_copy(2, (hsize_t)sizeof(uint8_t), size, dst_stride, half, src_stride, full);
/* Check */
for (i = 0; i < nx; i++) {
for (j = 0; j < ny; j++) {
if (full[4 * i * ny + 2 * j] != half[i * ny + j]) {
H5_FAILED();
if (!HDisatty(1)) {
AT();
printf(" full[%lu][%lu] != half[%lu][%lu]\n", (unsigned long)i * 2,
(unsigned long)j * 2, (unsigned long)i, (unsigned long)j);
printf(" full is:\n");
print_array(full, 2 * nx, 2 * ny, (size_t)1);
printf("\n half is:\n");
print_array(half, nx, ny, (size_t)1);
} /* end if */
goto error;
} /* end if */
} /* end for */
} /* end for */
PASSED();
/*
* Test replicating pixels to produce an image twice as large in each
* dimension.
*/
snprintf(s, sizeof(s), "Testing image sampling %4lux%-4lu to %4lux%-4lu ", (unsigned long)nx,
(unsigned long)ny, (unsigned long)(2 * nx), (unsigned long)(2 * ny));
printf("%-70s", s);
fflush(stdout);
/* Setup stride */
size[0] = nx;
size[1] = ny;
size[2] = 2;
size[3] = 2;
src_stride[0] = 0;
src_stride[1] = 1;
src_stride[2] = 0;
src_stride[3] = 0;
dst_stride[0] = (hsize_t)(2 * ny);
dst_stride[1] = (hsize_t)(2 * sizeof(uint8_t) - 4 * ny);
dst_stride[2] = (hsize_t)(2 * ny - 2 * sizeof(uint8_t));
dst_stride[3] = sizeof(uint8_t);
/* Copy */
H5VM_stride_copy(4, (hsize_t)sizeof(uint8_t), size, dst_stride, twice, src_stride, half);
/* Check */
s[0] = '\0';
for (i = 0; i < nx; i++) {
for (j = 0; j < ny; j++) {
if (half[i * ny + j] != twice[4 * i * ny + 2 * j])
snprintf(s, sizeof(s), "half[%lu][%lu] != twice[%lu][%lu]", (unsigned long)i,
(unsigned long)j, (unsigned long)i * 2, (unsigned long)j * 2);
else if (half[i * ny + j] != twice[4 * i * ny + 2 * j + 1])
snprintf(s, sizeof(s), "half[%lu][%lu] != twice[%lu][%lu]", (unsigned long)i,
(unsigned long)j, (unsigned long)i * 2, (unsigned long)j * 2 + 1);
else if (half[i * ny + j] != twice[(2 * i + 1) * 2 * ny + 2 * j])
snprintf(s, sizeof(s), "half[%lu][%lu] != twice[%lu][%lu]", (unsigned long)i,
(unsigned long)j, (unsigned long)i * 2 + 1, (unsigned long)j * 2);
else if (half[i * ny + j] != twice[(2 * i + 1) * 2 * ny + 2 * j + 1])
snprintf(s, sizeof(s), "half[%lu][%lu] != twice[%lu][%lu]", (unsigned long)i,
(unsigned long)j, (unsigned long)i * 2 + 1, (unsigned long)j * 2 + 1);
if (s[0]) {
H5_FAILED();
if (!HDisatty(1)) {
AT();
printf(" %s\n Half is:\n", s);
print_array(half, nx, ny, (size_t)1);
printf("\n Twice is:\n");
print_array(twice, 2 * nx, 2 * ny, (size_t)1);
} /* end if */
goto error;
} /* end if */
} /* end for */
} /* end for */
PASSED();
free(full);
free(half);
free(twice);
return SUCCEED;
error:
if (full)
free(full);
if (half)
free(half);
if (twice)
free(twice);
return FAIL;
} /* test_sub_super() */
/*-------------------------------------------------------------------------
* Function: test_array_fill
*
* Purpose: Tests H5VM_array_fill routine by copying a multibyte value
* (an array of ints, in our case) into all the elements of an
* array.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_array_fill(size_t lo, size_t hi)
{
int *dst = NULL; /* Destination */
int src[ARRAY_FILL_SIZE]; /* Source to duplicate */
size_t u, v, w; /* Local index variables */
char s[256];
snprintf(s, sizeof(s), "array filling %4lu-%-4lu elements", (unsigned long)lo, (unsigned long)hi);
TESTING(s);
/* Initialize */
if (NULL == (dst = (int *)calloc(sizeof(int), ARRAY_FILL_SIZE * hi)))
TEST_ERROR;
/* Setup */
for (u = 0; u < ARRAY_FILL_SIZE; u++)
src[u] = (char)u;
/* Fill */
for (w = lo; w <= hi; w++) {
H5VM_array_fill(dst, src, sizeof(src), w);
/* Check */
for (u = 0; u < w; u++)
for (v = 0; v < ARRAY_FILL_SIZE; v++)
if (dst[(u * ARRAY_FILL_SIZE) + v] != src[v])
TEST_ERROR;
memset(dst, 0, sizeof(int) * ARRAY_FILL_SIZE * w);
} /* end for */
PASSED();
free(dst);
return SUCCEED;
error:
if (dst)
free(dst);
return FAIL;
} /* end test_array_fill() */
/*-------------------------------------------------------------------------
* Function: test_array_offset_n_calc
*
* Purpose: Tests H5VM_array_offset and H5VM_array_calc routines by comparing
* computed array offsets against calculated ones and then going
* back to the coordinates from the offset and checking those.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_array_offset_n_calc(size_t n, size_t x, size_t y, size_t z)
{
hsize_t *a = NULL;
hsize_t *temp_a; /* Array for stored calculated offsets */
hsize_t off; /* Offset in array */
size_t u, v, w; /* Local index variables */
hsize_t dims[ARRAY_OFFSET_NDIMS]; /* X, Y & X coordinates of array to check */
hsize_t coords[ARRAY_OFFSET_NDIMS]; /* X, Y & X coordinates to check offset of */
hsize_t new_coords[ARRAY_OFFSET_NDIMS]; /* X, Y & X coordinates of offset */
char s[256];
snprintf(s, sizeof(s), "array offset %4lux%4lux%4lu elements", (unsigned long)z, (unsigned long)y,
(unsigned long)x);
TESTING(s);
/* Initialize */
if (NULL == (a = (hsize_t *)malloc(sizeof(hsize_t) * x * y * z)))
TEST_ERROR;
dims[0] = z;
dims[1] = y;
dims[2] = x;
/* Setup */
for (u = 0, temp_a = a, off = 0; u < z; u++)
for (v = 0; v < y; v++)
for (w = 0; w < x; w++)
*temp_a++ = off++;
/* Check offsets */
for (u = 0; u < n; u++) {
/* Get random coordinate */
coords[0] = (hsize_t)((size_t)rand() % z);
coords[1] = (hsize_t)((size_t)rand() % y);
coords[2] = (hsize_t)((size_t)rand() % x);
/* Get offset of coordinate */
off = H5VM_array_offset(ARRAY_OFFSET_NDIMS, dims, coords);
/* Check offset of coordinate */
if (a[off] != off)
TEST_ERROR;
/* Get coordinates of offset */
if (H5VM_array_calc(off, ARRAY_OFFSET_NDIMS, dims, new_coords) < 0)
TEST_ERROR;
/* Check computed coordinates */
for (v = 0; v < ARRAY_OFFSET_NDIMS; v++)
if (coords[v] != new_coords[v]) {
fprintf(stderr, "coords[%zu]=%" PRIuHSIZE ", new_coords[%zu]=%" PRIuHSIZE "\n", v, coords[v],
v, new_coords[v]);
TEST_ERROR;
} /* end if */
} /* end for */
PASSED();
free(a);
return SUCCEED;
error:
if (a)
free(a);
return FAIL;
} /* end test_array_offset_n_calc() */
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Test various hyperslab operations. Give the words
* 'small' and/or 'medium' on the command line or only 'small'
* is assumed.
*
* Return: EXIT_SUCCESS/EXIT_FAILURE
*
*-------------------------------------------------------------------------
*/
int
main(int argc, char *argv[])
{
herr_t status;
int nerrors = 0;
unsigned size_of_test;
/* Parse arguments or assume `small' & `medium' */
if (1 == argc)
size_of_test = TEST_SMALL | TEST_MEDIUM;
else {
int i;
for (i = 1, size_of_test = 0; i < argc; i++) {
if (!strcmp(argv[i], "small"))
size_of_test |= TEST_SMALL;
else if (!strcmp(argv[i], "medium"))
size_of_test |= TEST_MEDIUM;
else {
printf("unrecognized argument: %s\n", argv[i]);
exit(EXIT_FAILURE);
} /* end else */
} /* end for */
} /* end else */
printf("Test sizes: ");
if (size_of_test & TEST_SMALL)
printf(" SMALL");
if (size_of_test & TEST_MEDIUM)
printf(" MEDIUM");
printf("\n");
/* Set the random # seed */
srand((unsigned)time(NULL));
/*
* Open the library explicitly for thread-safe builds, so per-thread
* things are initialized correctly.
*/
#ifdef H5_HAVE_THREADSAFE
H5open();
#endif /* H5_HAVE_THREADSAFE */
/*
*------------------------------
* TEST HYPERSLAB FILL OPERATION
*------------------------------
*/
if (size_of_test & TEST_SMALL) {
status = test_fill((size_t)11, (size_t)0, (size_t)0, (size_t)1, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_fill((size_t)11, (size_t)10, (size_t)0, (size_t)1, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_fill((size_t)3, (size_t)5, (size_t)5, (size_t)1, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
} /* end if */
if (size_of_test & TEST_MEDIUM) {
status = test_fill((size_t)113, (size_t)0, (size_t)0, (size_t)1, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_fill((size_t)15, (size_t)11, (size_t)0, (size_t)1, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_fill((size_t)5, (size_t)7, (size_t)7, (size_t)1, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/*------------------------------
* TEST HYPERSLAB COPY OPERATION
*------------------------------
*/
/* exhaustive, one-dimensional test */
if (size_of_test & TEST_SMALL) {
status = test_copy(VARIABLE_SRC, (size_t)11, (size_t)0, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_DST, (size_t)11, (size_t)0, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_BOTH, (size_t)11, (size_t)0, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
} /* end if */
if (size_of_test & TEST_MEDIUM) {
status = test_copy(VARIABLE_SRC, (size_t)179, (size_t)0, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_DST, (size_t)179, (size_t)0, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_BOTH, (size_t)179, (size_t)0, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/* exhaustive, two-dimensional test */
if (size_of_test & TEST_SMALL) {
status = test_copy(VARIABLE_SRC, (size_t)11, (size_t)10, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_DST, (size_t)11, (size_t)10, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_BOTH, (size_t)11, (size_t)10, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
} /* end if */
if (size_of_test & TEST_MEDIUM) {
status = test_copy(VARIABLE_SRC, (size_t)13, (size_t)19, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_DST, (size_t)13, (size_t)19, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_BOTH, (size_t)13, (size_t)19, (size_t)0, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/* sparse, two-dimensional test */
if (size_of_test & TEST_MEDIUM) {
status = test_copy(VARIABLE_SRC, (size_t)73, (size_t)67, (size_t)0, (size_t)7, (size_t)11, (size_t)1,
(size_t)13, (size_t)11, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_DST, (size_t)73, (size_t)67, (size_t)0, (size_t)7, (size_t)11, (size_t)1,
(size_t)13, (size_t)11, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_BOTH, (size_t)73, (size_t)67, (size_t)0, (size_t)7, (size_t)11, (size_t)1,
(size_t)13, (size_t)11, (size_t)1);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/* exhaustive, three-dimensional test */
if (size_of_test & TEST_SMALL) {
status = test_copy(VARIABLE_SRC, (size_t)3, (size_t)5, (size_t)5, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_DST, (size_t)3, (size_t)5, (size_t)5, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_BOTH, (size_t)3, (size_t)5, (size_t)5, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
} /* end if */
if (size_of_test & TEST_MEDIUM) {
status = test_copy(VARIABLE_SRC, (size_t)7, (size_t)9, (size_t)5, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_DST, (size_t)7, (size_t)9, (size_t)5, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
status = test_copy(VARIABLE_BOTH, (size_t)7, (size_t)9, (size_t)5, (size_t)1, (size_t)1, (size_t)1,
(size_t)1, (size_t)1, (size_t)1);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/*---------------------
* TEST MULTI-BYTE FILL
*---------------------
*/
if (size_of_test & TEST_SMALL) {
status = test_multifill((size_t)10);
nerrors += status < 0 ? 1 : 0;
} /* end if */
if (size_of_test & TEST_MEDIUM) {
status = test_multifill((size_t)500000);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/*---------------------------
* TEST TRANSLATION OPERATORS
*---------------------------
*/
if (size_of_test & TEST_SMALL) {
status = test_endian((size_t)10);
nerrors += status < 0 ? 1 : 0;
status = test_transpose((size_t)9, (size_t)9);
nerrors += status < 0 ? 1 : 0;
status = test_transpose((size_t)3, (size_t)11);
nerrors += status < 0 ? 1 : 0;
} /* end if */
if (size_of_test & TEST_MEDIUM) {
status = test_endian((size_t)800000);
nerrors += status < 0 ? 1 : 0;
status = test_transpose((size_t)1200, (size_t)1200);
nerrors += status < 0 ? 1 : 0;
status = test_transpose((size_t)800, (size_t)1800);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/*-------------------------
* TEST SAMPLING OPERATIONS
*-------------------------
*/
if (size_of_test & TEST_SMALL) {
status = test_sub_super((size_t)5, (size_t)10);
nerrors += status < 0 ? 1 : 0;
} /* end if */
if (size_of_test & TEST_MEDIUM) {
status = test_sub_super((size_t)480, (size_t)640);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/*-------------------------
* TEST ARRAY FILL OPERATIONS
*-------------------------
*/
if (size_of_test & TEST_SMALL) {
status = test_array_fill((size_t)1, (size_t)9);
nerrors += status < 0 ? 1 : 0;
} /* end if */
if (size_of_test & TEST_MEDIUM) {
status = test_array_fill((size_t)9, (size_t)257);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/*-------------------------
* TEST ARRAY OFFSET OPERATIONS
*-------------------------
*/
if (size_of_test & TEST_SMALL) {
status = test_array_offset_n_calc((size_t)20, (size_t)7, (size_t)11, (size_t)13);
nerrors += status < 0 ? 1 : 0;
} /* end if */
if (size_of_test & TEST_MEDIUM) {
status = test_array_offset_n_calc((size_t)500, (size_t)71, (size_t)193, (size_t)347);
nerrors += status < 0 ? 1 : 0;
} /* end if */
/*--- END OF TESTS ---*/
if (nerrors) {
printf("***** %d HYPERSLAB TEST%s FAILED! *****\n", nerrors, 1 == nerrors ? "" : "S");
if (HDisatty(1))
printf("(Redirect output to a pager or a file to see debug output)\n");
exit(EXIT_FAILURE);
} /* end if */
printf("All hyperslab tests passed.\n");
#ifdef H5_HAVE_THREADSAFE
H5close();
#endif /* H5_HAVE_THREADSAFE */
exit(EXIT_SUCCESS);
}