Skip to content

Commit

Permalink
Support repeated values larger than 8-bit
Browse files Browse the repository at this point in the history
  • Loading branch information
FrancescAlted committed Feb 17, 2025
1 parent 14c3af1 commit 6d504a4
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 24 deletions.
1 change: 0 additions & 1 deletion blosc/b2nd.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,6 @@ int array_new(b2nd_context_t *ctx, int special_value, b2nd_array_t **array) {
if ((*array)->nitems != 0) {
int64_t nchunks = (*array)->extnitems / (*array)->chunknitems;
int64_t nitems = nchunks * (*array)->extchunknitems;
// blosc2_schunk_fill_special(sc, nitems, BLOSC2_SPECIAL_ZERO, chunksize);
BLOSC_ERROR(blosc2_schunk_fill_special(sc, nitems, special_value, chunksize));
}
(*array)->sc = sc;
Expand Down
13 changes: 6 additions & 7 deletions blosc/blosc2.c
Original file line number Diff line number Diff line change
Expand Up @@ -2160,7 +2160,7 @@ static int initialize_context_compression(
context->output_bytes = 0;
context->destsize = destsize;
context->sourcesize = srcsize;
context->typesize = (int32_t)typesize;
context->typesize = typesize;
context->filter_flags = filters_to_flags(filters);
for (int i = 0; i < BLOSC2_MAX_FILTERS; i++) {
context->filters[i] = filters[i];
Expand Down Expand Up @@ -4417,8 +4417,7 @@ int blosc2_chunk_nans(blosc2_cparams cparams, const int32_t nbytes, void* dest,
/* Create a chunk made of repeated values */
int blosc2_chunk_repeatval(blosc2_cparams cparams, const int32_t nbytes,
void* dest, int32_t destsize, const void* repeatval) {
uint8_t typesize = cparams.typesize;
if (destsize < BLOSC_EXTENDED_HEADER_LENGTH + typesize) {
if (destsize < BLOSC_EXTENDED_HEADER_LENGTH + cparams.typesize) {
BLOSC_TRACE_ERROR("dest buffer is not long enough");
return BLOSC2_ERROR_DATA;
}
Expand Down Expand Up @@ -4450,17 +4449,17 @@ int blosc2_chunk_repeatval(blosc2_cparams cparams, const int32_t nbytes,
header.version = BLOSC2_VERSION_FORMAT;
header.versionlz = BLOSC_BLOSCLZ_VERSION_FORMAT;
header.flags = BLOSC_DOSHUFFLE | BLOSC_DOBITSHUFFLE; // extended header
header.typesize = (uint8_t)typesize;
header.typesize = context->typesize;
header.nbytes = (int32_t)nbytes;
header.blocksize = context->blocksize;
header.cbytes = BLOSC_EXTENDED_HEADER_LENGTH + (int32_t)typesize;
header.cbytes = BLOSC_EXTENDED_HEADER_LENGTH + cparams.typesize;
header.blosc2_flags = BLOSC2_SPECIAL_VALUE << 4; // mark chunk as all repeated value
memcpy((uint8_t *)dest, &header, sizeof(header));
memcpy((uint8_t *)dest + sizeof(header), repeatval, typesize);
memcpy((uint8_t *)dest + sizeof(header), repeatval, cparams.typesize);

blosc2_free_ctx(context);

return BLOSC_EXTENDED_HEADER_LENGTH + (uint8_t)typesize;
return BLOSC_EXTENDED_HEADER_LENGTH + cparams.typesize;
}


Expand Down
2 changes: 1 addition & 1 deletion include/blosc2.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ enum {
BLOSC2_NO_SPECIAL = 0x0, //!< no special value
BLOSC2_SPECIAL_ZERO = 0x1, //!< zero special value
BLOSC2_SPECIAL_NAN = 0x2, //!< NaN special value
BLOSC2_SPECIAL_VALUE = 0x3, //!< generic special value
BLOSC2_SPECIAL_VALUE = 0x3, //!< repeated special value
BLOSC2_SPECIAL_UNINIT = 0x4, //!< non initialized values
BLOSC2_SPECIAL_LASTID = 0x4, //!< last valid ID for special value (update this adequately)
BLOSC2_SPECIAL_MASK = 0x7 //!< special value mask (prev IDs cannot be larger than this)
Expand Down
51 changes: 36 additions & 15 deletions tests/b2nd/test_b2nd_full.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,38 @@ CUTEST_TEST_SETUP(full) {
blosc2_init();

// Add parametrizations
CUTEST_PARAMETRIZE(typesize, uint8_t, CUTEST_DATA(
1, 2, 4, 8
CUTEST_PARAMETRIZE(typesize, int32_t, CUTEST_DATA(
//1, 2, 4, 8,
256, // 256, 257, 256 * 256,
// 256*256*256, 256*256*256*8 # these should work for small shapes as well, but are too slow
));
CUTEST_PARAMETRIZE(shapes, _test_shapes, CUTEST_DATA(
{0, {0}, {0}, {0}}, // 0-dim
{1, {5}, {3}, {2}}, // 1-idim
{2, {20, 0}, {7, 0}, {3, 0}}, // 0-shape
{2, {20, 10}, {7, 5}, {3, 5}}, // 0-shape
{2, {14, 10}, {8, 5}, {2, 2}}, // general,
{3, {12, 10, 14}, {3, 5, 9}, {3, 4, 4}}, // general
{3, {10, 21, 20, 5}, {8, 7, 15, 3}, {5, 5, 10, 1}}, // general,
{1, {3}, {3}, {3}}, // 1-idim
// {0, {0}, {0}, {0}}, // 0-dim
//{1, {5}, {3}, {2}}, // 1-idim
// {2, {20, 0}, {7, 0}, {3, 0}}, // 0-shape
// {2, {20, 10}, {7, 5}, {3, 5}}, // 0-shape
// {2, {14, 10}, {8, 5}, {2, 2}}, // general,
// {3, {12, 10, 14}, {3, 5, 9}, {3, 4, 4}}, // general
// {3, {10, 21, 20, 5}, {8, 7, 15, 3}, {5, 5, 10, 1}}, // general,
));
CUTEST_PARAMETRIZE(backend, _test_backend, CUTEST_DATA(
{false, false},
{true, false},
{true, true},
{false, true},
// {true, false},
// {true, true},
// {false, true},
));
CUTEST_PARAMETRIZE(fill_value, int8_t, CUTEST_DATA(
3, 113, 33, -5
//3, 113, 33, -5
3
));
}


CUTEST_TEST_TEST(full) {
CUTEST_GET_PARAMETER(backend, _test_backend);
CUTEST_GET_PARAMETER(shapes, _test_shapes);
CUTEST_GET_PARAMETER(typesize, uint8_t);
CUTEST_GET_PARAMETER(typesize, uint32_t);
CUTEST_GET_PARAMETER(fill_value, int8_t);

char *urlpath = "test_full.b2frame";
Expand Down Expand Up @@ -85,6 +89,10 @@ CUTEST_TEST_TEST(full) {
((int8_t *) value)[0] = fill_value;
break;
default:
// Fill a buffer with fill_value
for (int i = 0; i < typesize; ++i) {
value[i] = fill_value;
}
break;
}

Expand All @@ -96,6 +104,7 @@ CUTEST_TEST_TEST(full) {

/* Testing */
for (int i = 0; i < buffersize / typesize; ++i) {
uint8_t *buffer_fill = malloc(typesize);
bool is_true = false;
switch (typesize) {
case 8:
Expand All @@ -111,9 +120,21 @@ CUTEST_TEST_TEST(full) {
is_true = ((int8_t *) buffer_dest)[i] == fill_value;
break;
default:
// Fill a buffer with fill_value and compare with buffer_dest
for (int j = 0; j < typesize; ++j) {
buffer_fill[j] = fill_value;
}
// Compare buffer_fill with buffer_dest
is_true = memcmp(buffer_fill, buffer_dest, typesize) == 0;
// print the 10 first bytes of buffer_fill and buffer_dest
printf("buffer_fill: ");
for (int j = 0; j < 10; ++j) {
printf("%d vs %d ", buffer_fill[j], buffer_dest[j]);
}
free(buffer_fill);
break;
}
CUTEST_ASSERT("Elements are not equals", is_true);
CUTEST_ASSERT("Elements are not equal", is_true);
}

/* Free mallocs */
Expand Down

0 comments on commit 6d504a4

Please sign in to comment.