Skip to content

Commit 9d670ef

Browse files
committed
Preliminary test for b2nd_concatenate
1 parent ff7d474 commit 9d670ef

File tree

3 files changed

+202
-7
lines changed

3 files changed

+202
-7
lines changed

blosc/b2nd.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,8 +1330,8 @@ int b2nd_copy(b2nd_context_t *ctx, const b2nd_array_t *src, b2nd_array_t **array
13301330
}
13311331

13321332

1333-
int b2nd_concatenate(b2nd_context_t *ctx, b2nd_array_t **array, const b2nd_array_t *src1,
1334-
const b2nd_array_t *src2, int axis) {
1333+
int b2nd_concatenate(b2nd_context_t *ctx, const b2nd_array_t *src1,
1334+
const b2nd_array_t *src2, b2nd_array_t **array, int8_t axis) {
13351335
BLOSC_ERROR_NULL(src1, BLOSC2_ERROR_NULL_POINTER);
13361336
BLOSC_ERROR_NULL(src2, BLOSC2_ERROR_NULL_POINTER);
13371337
BLOSC_ERROR_NULL(array, BLOSC2_ERROR_NULL_POINTER);
@@ -1346,7 +1346,7 @@ int b2nd_concatenate(b2nd_context_t *ctx, b2nd_array_t **array, const b2nd_array
13461346
}
13471347
// Compute the new shape
13481348
int64_t newshape[B2ND_MAX_DIM];
1349-
for (int i = 0; i < src1->ndim; ++i) {
1349+
for (int8_t i = 0; i < src1->ndim; ++i) {
13501350
if (i == axis) {
13511351
newshape[i] = src1->shape[i] + src2->shape[i];
13521352
} else {
@@ -1362,7 +1362,7 @@ int b2nd_concatenate(b2nd_context_t *ctx, b2nd_array_t **array, const b2nd_array
13621362
BLOSC_ERROR(b2nd_resize(*array, newshape, NULL));
13631363

13641364
// Copy the data from the second array
1365-
int64_t start[B2ND_MAX_DIM] = {0};
1365+
int64_t start[B2ND_MAX_DIM];
13661366
int64_t stop[B2ND_MAX_DIM];
13671367
// Copy chunk by chunk
13681368
void *buffer = malloc(src2->sc->typesize * src2->extchunknitems);
@@ -1372,10 +1372,10 @@ int b2nd_concatenate(b2nd_context_t *ctx, b2nd_array_t **array, const b2nd_array
13721372
src2->sc->typesize * src2->extchunknitems));
13731373
// Get multidimensional chunk position
13741374
int64_t nchunk_ndim[B2ND_MAX_DIM] = {0};
1375-
blosc2_unidim_to_multidim(src2->ndim, src2->chunkshape, nchunk, nchunk_ndim);
1375+
blosc2_unidim_to_multidim(src2->ndim, (int64_t*)(src2->chunkshape), nchunk, nchunk_ndim);
13761376

13771377
// Set positions for each dimension
1378-
for (int i = 0; i < src2->ndim; ++i) {
1378+
for (int8_t i = 0; i < src2->ndim; ++i) {
13791379
start[i] = nchunk_ndim[i] * src2->chunkshape[i];
13801380
stop[i] = start[i] + src2->chunkshape[i];
13811381
if (stop[i] > src2->shape[i]) {
@@ -1390,7 +1390,7 @@ int b2nd_concatenate(b2nd_context_t *ctx, b2nd_array_t **array, const b2nd_array
13901390
}
13911391

13921392
// Copy the chunk to the correct position
1393-
BLOSC_ERROR(b2nd_set_slice_cbuffer(buffer, src2->chunkshape,
1393+
BLOSC_ERROR(b2nd_set_slice_cbuffer(buffer, (int64_t*)(src2->chunkshape),
13941394
src2->sc->typesize * src2->extchunknitems,
13951395
start, stop, *array));
13961396
}

include/b2nd.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,23 @@ BLOSC_EXPORT int b2nd_set_slice_cbuffer(const void *buffer, const int64_t *buffe
409409
*/
410410
BLOSC_EXPORT int b2nd_copy(b2nd_context_t *ctx, const b2nd_array_t *src, b2nd_array_t **array);
411411

412+
/**
413+
* @brief Concatenate arrays. The result is stored in a new b2nd array.
414+
*
415+
* @param ctx The b2nd context for the new array.
416+
* @param src1 The first array from which data is copied.
417+
* @param src2 The second array from which data is copied.
418+
* @param array The memory pointer where the array will be created.
419+
* @param axis The axis along which the arrays will be concatenated.
420+
*
421+
* @return An error code
422+
*
423+
* @note The ndim and shape in ctx will be overwritten by the src1 ctx.
424+
*
425+
*/
426+
BLOSC_EXPORT int b2nd_concatenate(b2nd_context_t *ctx, const b2nd_array_t *src1, const b2nd_array_t *src2,
427+
b2nd_array_t **array, int8_t axis);
428+
412429
/**
413430
* @brief Print metalayer parameters.
414431
*

tests/b2nd/test_b2nd_concatenate.c

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*********************************************************************
2+
Blosc - Blocked Shuffling and Compression Library
3+
4+
Copyright (c) 2021 Blosc Development Team <blosc@blosc.org>
5+
https://blosc.org
6+
License: BSD 3-Clause (see LICENSE.txt)
7+
8+
See LICENSE.txt for details about copyright and rights to use.
9+
**********************************************************************/
10+
11+
#include "test_common.h"
12+
13+
typedef struct {
14+
int8_t ndim;
15+
int64_t shape[B2ND_MAX_DIM];
16+
int32_t chunkshape[B2ND_MAX_DIM];
17+
int32_t blockshape[B2ND_MAX_DIM];
18+
int64_t start[B2ND_MAX_DIM];
19+
int64_t stop[B2ND_MAX_DIM];
20+
} test_shapes_t;
21+
22+
23+
CUTEST_TEST_SETUP(concatenate) {
24+
blosc2_init();
25+
26+
// Add parametrizations
27+
CUTEST_PARAMETRIZE(typesize, uint8_t, CUTEST_DATA(
28+
1,
29+
2,
30+
4,
31+
8,
32+
));
33+
34+
CUTEST_PARAMETRIZE(backend, _test_backend, CUTEST_DATA(
35+
{false, false},
36+
{true, false},
37+
{true, true},
38+
{false, true},
39+
));
40+
41+
42+
CUTEST_PARAMETRIZE(shapes, test_shapes_t, CUTEST_DATA(
43+
// {0, {0}, {0}, {0}, {0}, {0}}, // 0-dim
44+
// {1, {5}, {3}, {2}, {2}, {5}}, // 1-idim
45+
// {2, {20, 0}, {7, 0}, {3, 0}, {2, 0}, {8, 0}}, // 0-shape
46+
// {2, {20, 10}, {7, 5}, {3, 5}, {2, 0}, {18, 0}}, // 0-shape
47+
// {2, {14, 10}, {8, 5}, {2, 2}, {5, 3}, {9, 10}},
48+
// {3, {12, 10, 14}, {3, 5, 9}, {3, 4, 4}, {3, 0, 3}, {6, 7, 10}},
49+
// {4, {10, 21, 30, 5}, {8, 7, 15, 3}, {5, 5, 10, 1}, {5, 4, 3, 3}, {10, 8, 8, 4}},
50+
{2, {50, 50}, {25, 13}, {8, 8}, {0, 0}, {10, 10}},
51+
// The case below makes qemu-aarch64 (AARCH64 emulation) in CI (Ubuntu 22.04) to crash with a segfault.
52+
// Interestingly, this works perfectly well on both intel64 (native) and in aarch64 (emulated via docker).
53+
// Moreover, valgrind does not issue any warning at all when run in the later platforms.
54+
// In conclusion, this *may* be revealing a bug in the qemu-aarch64 binaries in Ubuntu 22.04.
55+
// {2, {143, 41}, {18, 13}, {7, 7}, {4, 2}, {6, 5}},
56+
// Replacing the above line by this one makes qemu-aarch64 happy.
57+
// {2, {150, 45}, {15, 15}, {7, 7}, {4, 2}, {6, 5}},
58+
// {2, {10, 10}, {5, 7}, {2, 2}, {0, 0}, {5, 5}},
59+
// // Checks for fast path in setting a single chunk that is C contiguous
60+
// {2, {20, 20}, {10, 10}, {5, 10}, {10, 10}, {20, 20}},
61+
// {3, {3, 4, 5}, {1, 4, 5}, {1, 2, 5}, {1, 0, 0}, {2, 4, 5}},
62+
// {3, {3, 8, 5}, {1, 4, 5}, {1, 2, 5}, {1, 4, 0}, {2, 8, 5}},
63+
));
64+
CUTEST_PARAMETRIZE(fill_value, int8_t, CUTEST_DATA(
65+
3, 113, 33, -5
66+
));
67+
68+
}
69+
70+
CUTEST_TEST_TEST(concatenate) {
71+
CUTEST_GET_PARAMETER(backend, _test_backend);
72+
CUTEST_GET_PARAMETER(shapes, test_shapes_t);
73+
CUTEST_GET_PARAMETER(typesize, uint8_t);
74+
CUTEST_GET_PARAMETER(fill_value, int8_t);
75+
76+
char *urlpath = "test_concatenate.b2frame";
77+
blosc2_remove_urlpath(urlpath);
78+
79+
blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
80+
cparams.nthreads = 2;
81+
cparams.typesize = typesize;
82+
blosc2_storage b2_storage = {.cparams=&cparams};
83+
if (backend.persistent) {
84+
b2_storage.urlpath = urlpath;
85+
}
86+
b2_storage.contiguous = backend.contiguous;
87+
88+
b2nd_context_t *ctx = b2nd_create_ctx(&b2_storage, shapes.ndim, shapes.shape,
89+
shapes.chunkshape, shapes.blockshape, NULL, 0, NULL, 0);
90+
91+
/* Create dest buffer */
92+
int64_t shape[B2ND_MAX_DIM] = {0};
93+
int64_t buffersize = typesize;
94+
for (int i = 0; i < ctx->ndim; ++i) {
95+
shape[i] = shapes.stop[i] - shapes.start[i];
96+
buffersize *= shape[i];
97+
}
98+
99+
// uint8_t *buffer = malloc(buffersize);
100+
// CUTEST_ASSERT("Buffer filled incorrectly", fill_buf(buffer, typesize, buffersize / typesize));
101+
102+
/* Create src1 with zeros */
103+
b2nd_array_t *src1;
104+
BLOSC_ERROR(b2nd_zeros(ctx, &src1));
105+
106+
/* Create src2 with ones */
107+
b2nd_array_t *src2;
108+
uint8_t *value = malloc(typesize);
109+
switch (typesize) {
110+
case 8:
111+
((int64_t *) value)[0] = (int64_t) fill_value;
112+
break;
113+
case 4:
114+
((int32_t *) value)[0] = (int32_t) fill_value;
115+
break;
116+
case 2:
117+
((int16_t *) value)[0] = (int16_t) fill_value;
118+
break;
119+
case 1:
120+
((int8_t *) value)[0] = fill_value;
121+
break;
122+
default:
123+
// Fill a buffer with fill_value
124+
for (int i = 0; i < typesize; ++i) {
125+
value[i] = fill_value;
126+
}
127+
break;
128+
}
129+
B2ND_TEST_ASSERT(b2nd_full(ctx, &src2, value));
130+
131+
/* Concatenate src1 and src2 */
132+
b2nd_array_t *array = NULL;
133+
B2ND_TEST_ASSERT(b2nd_concatenate(ctx, src1, src2, &array, 0));
134+
135+
// for (uint64_t i = 0; i < (uint64_t) buffersize / typesize; ++i) {
136+
// uint64_t k = i + 1;
137+
// switch (typesize) {
138+
// case 8:
139+
// CUTEST_ASSERT("Elements are not equals!",
140+
// (uint64_t) k == ((uint64_t *) destbuffer)[i]);
141+
// break;
142+
// case 4:
143+
// CUTEST_ASSERT("Elements are not equals!",
144+
// (uint32_t) k == ((uint32_t *) destbuffer)[i]);
145+
// break;
146+
// case 2:
147+
// CUTEST_ASSERT("Elements are not equals!",
148+
// (uint16_t) k == ((uint16_t *) destbuffer)[i]);
149+
// break;
150+
// case 1:
151+
// CUTEST_ASSERT("Elements are not equals!",
152+
// (uint8_t) k == ((uint8_t *) destbuffer)[i]);
153+
// break;
154+
// default:
155+
// B2ND_TEST_ASSERT(BLOSC2_ERROR_INVALID_PARAM);
156+
// }
157+
// }
158+
159+
/* Free mallocs */
160+
// free(buffer);
161+
// free(destbuffer);
162+
free(value);
163+
B2ND_TEST_ASSERT(b2nd_free(src1));
164+
B2ND_TEST_ASSERT(b2nd_free(src2));
165+
B2ND_TEST_ASSERT(b2nd_free(array));
166+
B2ND_TEST_ASSERT(b2nd_free_ctx(ctx));
167+
blosc2_remove_urlpath(urlpath);
168+
169+
return 0;
170+
}
171+
172+
CUTEST_TEST_TEARDOWN(concatenate) {
173+
blosc2_destroy();
174+
}
175+
176+
int main() {
177+
CUTEST_TEST_RUN(concatenate);
178+
}

0 commit comments

Comments
 (0)