Skip to content
Snippets Groups Projects
Commit b402a986 authored by Dominik Loidolt's avatar Dominik Loidolt
Browse files

refactor and test for encode_value_zero

parent cea4951a
Branches
Tags
1 merge request!11decompression/compression for non-imagette data
......@@ -26,6 +26,52 @@
/* return code if the bitstream buffer is too small to store the whole bitstream */
#define CMP_ERROR_SAMLL_BUF -2
/* pointer to a code word generation function */
typedef uint32_t (*generate_cw_pt)(uint32_t value, uint32_t encoder_par1,
uint32_t encoder_par2, uint32_t *cw);
/* typedef uint32_t (*next_model_f_pt)(uint32_t model_mode_val, uint32_t diff_model_var); */
struct encoder_setupt {
/* unsigned int lossy_par; */
/* next_model_f_pt *next_model_f; */
generate_cw_pt generate_cw; /* pointer to the code word generation function */
/* uint32_t updated_model; */
uint32_t encoder_par1;
uint32_t encoder_par2;
uint32_t outlier_par;
uint32_t model_value;
uint32_t max_value_bits; /* how many bits are needed to represent the highest possible value */
uint32_t max_bit_len; /* maximum length of the bitstream/icu_output_buf in bits */
uint32_t *bitstream_adr;
};
/**
* @brief map a signed value into a positive value range
*
* @param value_to_map signed value to map
* @param max_value_bits how many bits are needed to represent the
* highest possible value
*
* @returns the positive mapped value
*/
static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_value_bits)
{
uint32_t mask = (~0U >> (32 - max_value_bits)); /* mask the used bits */
value_to_map &= mask;
if (value_to_map >> (max_value_bits - 1)) { /* check the leading signed bit */
value_to_map |= ~mask; /* convert to 32-bit signed integer */
/* map negative values to uneven numbers */
return (-value_to_map) * 2 - 1; /* possible integer overflow is intended */
} else {
/* map positive values to even numbers */
return value_to_map * 2; /* possible integer overflow is intended */
}
}
/**
* @brief put the value of up to 32 bits into a bitstream accessed as 32-bit
......@@ -43,8 +89,6 @@
* @returns length in bits of the generated bitstream on success; returns
* negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
* the bitstream buffer is too small to put the value in the bitstream
* @note a value with more bits set as the n_bits parameter is considered as an
* erroneous input.
*/
static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
......@@ -60,21 +104,11 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
return -1;
if (n_bits == 0)
return 0;
return stream_len;
if (n_bits > 32)
return -1;
/* (M) is the n_bits parameter large enough to cover all value bits; the
* calculations can be re-used in the unsegmented code, so we have no overhead
*/
shiftRight = 32 - n_bits;
mask = 0xFFFFFFFFU >> shiftRight;
if (value & ~mask) {
debug_print("Error: Not all set bits in the put value are added to the bitstream. Check value n_bits parameter combination.\n");
return -1;
}
/* Do we need to write data to the bitstream? */
if (!bitstream_adr)
return stream_len;
......@@ -85,6 +119,13 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
return CMP_ERROR_SAMLL_BUF;
}
/* (M) is the n_bits parameter large enough to cover all value bits; the
* calculations can be re-used in the unsegmented code, so we have no overhead
*/
shiftRight = 32 - n_bits;
mask = 0xFFFFFFFFU >> shiftRight;
value &= mask;
/* Separate the bit_offset into word offset (set local_adr pointer) and local bit offset (bitsLeft) */
local_adr = bitstream_adr + (bit_offset >> 5);
bitsLeft = bit_offset & 0x1F;
......@@ -163,3 +204,235 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
return stream_len;
}
/**
* @brief forms the codeword according to the Rice code
*
* @param value value to be encoded
* @param m Golomb parameter, only m's which are power of 2 are allowed
* @param log2_m Rice parameter, is log_2(m) calculate outside function
* for better performance
* @param cw address were the encode code word is stored
*
* @returns the length of the formed code word in bits
* @note no check if the generated code word is not longer than 32 bits.
*/
static uint32_t Rice_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
uint32_t *cw)
{
uint32_t g; /* quotient of value/m */
uint32_t q; /* quotient code without ending zero */
uint32_t r; /* remainder of value/m */
uint32_t rl; /* remainder length */
g = value >> log2_m; /* quotient, number of leading bits */
q = (1U << g) - 1; /* prepare the quotient code without ending zero */
r = value & (m-1); /* calculate the remainder */
rl = log2_m + 1; /* length of the remainder (+1 for the 0 in the quotient code) */
*cw = (q << rl) | r; /* put the quotient and remainder code together */
/*
* NOTE: If log2_m = 31 -> rl = 32, (q << rl) leads to an undefined
* behavior. However, in this case, a valid code with a maximum of 32
* bits can only be formed if q = 0. Any shift with 0 << x always
* results in 0, which forms the correct codeword in this case. For
* performance reasons, this undefined behaviour is not caught.
*/
return rl + g; /* calculate the length of the code word */
}
/**
* @brief forms a codeword according to the Golomb code
*
* @param value value to be encoded
* @param m Golomb parameter (have to be bigger than 0)
* @param log2_m is log_2(m) calculate outside function for better
* performance
* @param cw address were the formed code word is stored
*
* @returns the length of the formed code word in bits
*/
static uint32_t Golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
uint32_t *cw)
{
uint32_t len0, b, g, q, lg;
uint32_t len;
uint32_t cutoff;
len0 = log2_m + 1; /* codeword length in group 0 */
cutoff = (1U << (log2_m + 1)) - m; /* members in group 0 */
if (value < cutoff) { /* group 0 */
*cw = value;
len = len0;
} else { /* other groups */
g = (value-cutoff) / m; /* this group is which one */
b = cutoff << 1; /* form the base codeword */
lg = len0 + g; /* it has lg remainder bits */
q = (1U << g) - 1; /* prepare the left side in unary */
*cw = (q << (len0+1)) + b + (value-cutoff) - g*m; /* composed codeword */
len = lg + 1; /* length of the codeword */
}
return len;
}
/**
* @brief generate a code word without a outlier mechanism and put in the
* bitstream
*
* @param value value to encode in the bitstream
* @param stream_len length of the bitstream in bits
* @param setup pointer to the encoder setup
*
* @returns the bit length of the bitstream with the added encoded value on
* success; negative on error
*/
static int encode_normal(uint32_t value, int stream_len,
struct encoder_setupt *setup)
{
uint32_t code_word, cw_len;
cw_len = setup->generate_cw(value, setup->encoder_par1,
setup->encoder_par2, &code_word);
return put_n_bits32(code_word, cw_len, stream_len, setup->bitstream_adr,
setup->max_bit_len);
}
/**
* @brief subtract the model from the data and encode the result and put it into
* bitstream, for outlier use the zero escape symbol mechanism
*
* @param data data to encode
* @param model model of the data (0 if not used)
* @param stream_len length of the bitstream in bits
* @param setup pointer to the encoder setup
*
* @returns the bit length of the bitstream with the added encoded value on
* success; negative on error
*
* @note no check if data or model are in the allowed range
*/
static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
struct encoder_setupt *setup)
{
data -= model;
data = map_to_pos(data, setup->max_value_bits);
/* For performance reasons we check if there is an outlier before adding
* one to the data, than the other way around:
* data++;
* if (data < setup->outlier_par && data != 0)
* return ...
*/
if (data < (setup->outlier_par - 1)) {
data++; /* add 1 to every value so we can use 0 as escape symbol */
return encode_normal(data, stream_len, setup);
}
data++; /* add 1 to every value so we can use 0 as escape symbol */
/* use zero as escape symbol */
stream_len = encode_normal(0, stream_len, setup);
if (stream_len <= 0)
return stream_len;
/* put the data unencoded in the bitstream */
stream_len = put_n_bits32(data, setup->max_value_bits, stream_len,
setup->bitstream_adr, setup->max_bit_len);
return stream_len;
}
static int cal_multi_offset(unsigned int unencoded_data)
{
if (unencoded_data <= 0x3)
return 0;
if (unencoded_data <= 0xF)
return 1;
if (unencoded_data <= 0x3F)
return 2;
if (unencoded_data <= 0xFF)
return 3;
if (unencoded_data <= 0x3FF)
return 4;
if (unencoded_data <= 0xFFF)
return 5;
if (unencoded_data <= 0x3FFF)
return 6;
if (unencoded_data <= 0xFFFF)
return 7;
if (unencoded_data <= 0x3FFFF)
return 8;
if (unencoded_data <= 0xFFFFF)
return 9;
if (unencoded_data <= 0x3FFFFF)
return 10;
if (unencoded_data <= 0xFFFFFF)
return 11;
if (unencoded_data <= 0x3FFFFFF)
return 12;
if (unencoded_data <= 0xFFFFFFF)
return 13;
if (unencoded_data <= 0x3FFFFFFF)
return 14;
else
return 15;
}
#if 0
static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
struct encoder_setupt *setup)
{
uint32_t unencoded_data;
unsigned int unencoded_data_len;
uint32_t escape_sym;
uint32_t escape_sym_offset;
data -= model; /* possible underflow is intended */
data = map_to_pos(data, setup->max_value_bits);
if (data < setup->outlier_par)
return encode_normal(data, stream_len, setup);
/*
* In this mode we put the difference between the data and the spillover
* threshold value (unencoded_data) after a encoded escape symbol, which
* indicate that the next codeword is unencoded.
* We use different escape symbol depended on the size the needed bit of
* unencoded data:
* 0, 1, 2 bits needed for unencoded data -> escape symbol is spill + 0
* 3, 4 bits needed for unencoded data -> escape symbol is spill + 1
* ..
*/
unencoded_data = data - setup->outlier_par;
escape_sym_offset = cal_multi_offset(unencoded_data);
escape_sym = setup->outlier_par + escape_sym_offset;
unencoded_data_len = (escape_sym_offset + 1) * 2;
/* put the escape symbol in the bitstream */
stream_len = encode_normal(escape_sym, stream_len, setup);
if (stream_len <= 0)
return stream_len;
/* put the unencoded data in the bitstream */
stream_len = put_n_bits32(unencoded_data, unencoded_data_len, stream_len,
setup->bitstream_adr, setup->max_bit_len);
return stream_len;
}
#endif
......@@ -2,10 +2,99 @@
#include "unity.h"
#include "cmp_support.h"
/* this is a hack to test static functions */
#include "../lib/cmp_icu_new.c"
/**
* @test map_to_pos
*/
void test_map_to_pos(void)
{
uint32_t value_to_map;
uint32_t max_value_bits;
uint32_t mapped_value;
/* test mapping 32 bits values */
max_value_bits = 32;
value_to_map = 0;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(0, mapped_value);
value_to_map = -1U;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(1, mapped_value);
value_to_map = 1;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(2, mapped_value);
value_to_map = 42;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(84, mapped_value);
value_to_map = INT32_MAX;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_HEX(UINT32_MAX-1, mapped_value);
value_to_map = INT32_MIN;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_HEX(UINT32_MAX, mapped_value);
/* test mapping 16 bits values */
max_value_bits = 16;
value_to_map = -1U;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(1, mapped_value);
/* test mapping 6 bits values */
max_value_bits = 6;
value_to_map = 0;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(0, mapped_value);
value_to_map = -1U;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(1, mapped_value);
value_to_map = UINT32_MAX;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(1, mapped_value);
value_to_map = -1U & 0x3FU;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(1, mapped_value);
value_to_map = 63;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(1, mapped_value);
value_to_map = 1;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(2, mapped_value);
value_to_map = 31;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(62, mapped_value);
value_to_map = -33U; /* aka 31 */
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(62, mapped_value);
value_to_map = -32U;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(63, mapped_value);
value_to_map = 32;
mapped_value = map_to_pos(value_to_map, max_value_bits);
TEST_ASSERT_EQUAL_INT(63, mapped_value);
}
/**
* @test put_n_bits32
......@@ -42,7 +131,11 @@ void test_put_n_bits32(void)
init_PB32_arrays(testarray0, testarray1);
TEST_ASSERT(testarray0[0] == 0);
TEST_ASSERT(testarray0[1] == 0);
TEST_ASSERT(testarray0[2] == 0);
TEST_ASSERT(testarray1[0] == 0xffffffff);
TEST_ASSERT(testarray1[1] == 0xffffffff);
TEST_ASSERT(testarray1[2] == 0xffffffff);
/*** n=0 ***/
......@@ -56,7 +149,9 @@ void test_put_n_bits32(void)
TEST_ASSERT_EQUAL_INT(0, rval);
TEST_ASSERT(testarray1[0] == 0xffffffff);
/* TODO: not a valid test */
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(0, rval);
v = 0xffffffff; n = 0; o = 0;
rval = put_n_bits32(v, n, o, testarray0, l);
TEST_ASSERT_EQUAL_INT(0, rval);
......@@ -66,27 +161,35 @@ void test_put_n_bits32(void)
TEST_ASSERT_EQUAL_INT(0, rval);
TEST_ASSERT(testarray1[0] == 0xffffffff);
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(0, rval);
/* do not write, right border */
v = 0; n = 0; o = 31;
v = 0; n = 0; o = l;
rval = put_n_bits32(v, n, o, testarray0, l);
TEST_ASSERT_EQUAL_INT(0, rval);
TEST_ASSERT_EQUAL_INT(l, rval);
TEST_ASSERT(testarray0[0] == 0);
rval = put_n_bits32(v, n, o, testarray1, l);
TEST_ASSERT_EQUAL_INT(0, rval);
TEST_ASSERT_EQUAL_INT(l, rval);
TEST_ASSERT(testarray1[0] == 0xffffffff);
/* TODO: not a valid test */
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(l, rval);
/* test value = 0xffffffff; N = 0 */
v = 0xffffffff; n = 0; o = 31;
v = 0xffffffff; n = 0; o = l;
rval = put_n_bits32(v, n, o, testarray0, l);
TEST_ASSERT_EQUAL_INT(0, rval);
TEST_ASSERT_EQUAL_INT(l, rval);
TEST_ASSERT(testarray0[0] == 0);
rval = put_n_bits32(v, n, o, testarray1, l);
TEST_ASSERT_EQUAL_INT(0, rval);
TEST_ASSERT_EQUAL_INT(l, rval);
TEST_ASSERT(testarray1[0] == 0xffffffff);
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(l, rval);
/*** n=1 ***/
/* left border, write 0 */
......@@ -114,10 +217,12 @@ void test_put_n_bits32(void)
rval = put_n_bits32(v, n, o, testarray0, l);
TEST_ASSERT_EQUAL_INT(rval, 32);
TEST_ASSERT(testarray0[0] == 0xf0f0abcd);
TEST_ASSERT(testarray0[1] == 0);
rval = put_n_bits32(v, n, o, testarray1, l);
TEST_ASSERT_EQUAL_INT(rval, 32);
TEST_ASSERT(testarray1[0] == 0xf0f0abcd);
TEST_ASSERT(testarray1[1] == 0xffffffff);
/* re-init input arrays after clobbering */
init_PB32_arrays(testarray0, testarray1);
......@@ -317,26 +422,49 @@ void test_put_n_bits32(void)
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(rval, 97); /* rval can be longer than l */
/* error cases */
/* n too large */
v = 0x0; n = 33; o = 1;
/* value larger than n allows */
v = 0x7f; n = 6; o = 10;
rval = put_n_bits32(v, n, o, testarray0, l);
TEST_ASSERT_EQUAL_INT(rval, -1);
TEST_ASSERT(testarray0[0] == 0);
TEST_ASSERT_EQUAL_INT(16, rval);
TEST_ASSERT(testarray0[0] == 0x003f0000);
TEST_ASSERT(testarray0[1] == 0);
rval = put_n_bits32(v, n, o, testarray1, l);
TEST_ASSERT_EQUAL_INT(16, rval);
TEST_ASSERT(testarray1[0] == 0xffffffff);
TEST_ASSERT(testarray1[1] == 0xffffffff);
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(rval, -1);
TEST_ASSERT_EQUAL_INT(16, rval);
/* re-init input arrays after clobbering */
init_PB32_arrays(testarray0, testarray1);
/* value larger than n allows */
v = 0x7f; n = 6; o = 10;
v = 0xffffffff; n = 6; o = 10;
rval = put_n_bits32(v, n, o, testarray0, l);
TEST_ASSERT_EQUAL_INT(-1, rval);
TEST_ASSERT_EQUAL_INT(16, rval);
TEST_ASSERT(testarray0[0] == 0x003f0000);
TEST_ASSERT(testarray0[1] == 0);
rval = put_n_bits32(v, n, o, testarray1, l);
TEST_ASSERT_EQUAL_INT(16, rval);
TEST_ASSERT(testarray1[0] == 0xffffffff);
TEST_ASSERT(testarray1[1] == 0xffffffff);
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(16, rval);
/* re-init input arrays after clobbering */
init_PB32_arrays(testarray0, testarray1);
/*** error cases ***/
/* n too large */
v = 0x0; n = 33; o = 1;
rval = put_n_bits32(v, n, o, testarray0, l);
TEST_ASSERT_EQUAL_INT(rval, -1);
TEST_ASSERT(testarray0[0] == 0);
TEST_ASSERT(testarray0[1] == 0);
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(-1, rval);
TEST_ASSERT_EQUAL_INT(rval, -1);
/* try to put too much in the bitstream */
v = 0x1; n = 1; o = 96;
......@@ -346,11 +474,11 @@ void test_put_n_bits32(void)
TEST_ASSERT(testarray0[1] == 0);
TEST_ASSERT(testarray0[2] == 0);
/* this should work */
/* this should work (if bitstream=NULL no length check) */
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(97, rval);
/* offset lager than max_bit_len */
/* offset lager than max_bit_len(l) */
v = 0x0; n = 32; o = INT32_MAX;
rval = put_n_bits32(v, n, o, testarray1, l);
TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
......@@ -370,4 +498,305 @@ void test_put_n_bits32(void)
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(-1, rval);
v = 0x0; n = 0; o = -2;
rval = put_n_bits32(v, n, o, testarray0, l);
TEST_ASSERT_EQUAL_INT(-1, rval);
TEST_ASSERT(testarray0[0] == 0);
TEST_ASSERT(testarray0[1] == 0);
rval = put_n_bits32(v, n, o, NULL, l);
TEST_ASSERT_EQUAL_INT(-1, rval);
}
/**
* @test Rice_encoder
*/
void test_Rice_encoder(void)
{
uint32_t value, g_par, log2_g_par, cw, cw_len;
/* test minimum Golomb parameter */
value = 0; log2_g_par = (uint32_t)ilog_2(MIN_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(1, cw_len);
TEST_ASSERT_EQUAL_HEX(0x0, cw);
value = 31;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
/* test some arbitrary values */
value = 0; log2_g_par = 4; g_par = 1U << log2_g_par; cw = ~0U;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(5, cw_len);
TEST_ASSERT_EQUAL_HEX(0x0, cw);
value = 1;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(5, cw_len);
TEST_ASSERT_EQUAL_HEX(0x1, cw);
value = 42;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(7, cw_len);
TEST_ASSERT_EQUAL_HEX(0x6a, cw);
value = 446;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
value = 447;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
/* test maximum Golomb parameter for Rice_encoder */
value = 0; log2_g_par = (uint32_t)ilog_2(MAX_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0x0, cw);
value = 1;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0x1, cw);
value = 0x7FFFFFFE;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
value = 0x7FFFFFFF;
cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
}
/**
* @test Golomb_encoder
*/
void test_Golomb_encoder(void)
{
uint32_t value, g_par, log2_g_par, cw, cw_len;
/* test minimum Golomb parameter */
value = 0; g_par = MIN_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(1, cw_len);
TEST_ASSERT_EQUAL_HEX(0x0, cw);
value = 31;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
/* test some arbitrary values with g_par = 16 */
value = 0; g_par = 16; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(5, cw_len);
TEST_ASSERT_EQUAL_HEX(0x0, cw);
value = 1;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(5, cw_len);
TEST_ASSERT_EQUAL_HEX(0x1, cw);
value = 42;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(7, cw_len);
TEST_ASSERT_EQUAL_HEX(0x6a, cw);
value = 446;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
value = 447;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
/* test some arbitrary values with g_par = 3 */
value = 0; g_par = 3; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(2, cw_len);
TEST_ASSERT_EQUAL_HEX(0x0, cw);
value = 1;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(3, cw_len);
TEST_ASSERT_EQUAL_HEX(0x2, cw);
value = 42;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(16, cw_len);
TEST_ASSERT_EQUAL_HEX(0xFFFC, cw);
value = 44;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(17, cw_len);
TEST_ASSERT_EQUAL_HEX(0x1FFFB, cw);
value = 88;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFA, cw);
value = 89;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFB, cw);
/* test maximum Golomb parameter for Golomb_encoder */
value = 0; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0x0, cw);
value = 1; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0x1, cw);
value = 0x7FFFFFFE;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
value = 0x7FFFFFFF;
cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
TEST_ASSERT_EQUAL_INT(32, cw_len);
TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
}
/**
* @test encode_value_zero
*/
void test_encode_value_zero(void)
{
uint32_t data, model;
int stream_len;
struct encoder_setupt setup = {0};
uint32_t bitstream[3] = {0};
/* setup the setup */
setup.encoder_par1 = 1;
setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
setup.outlier_par = 32;
setup.max_value_bits = 32;
setup.generate_cw = Rice_encoder;
setup.bitstream_adr = bitstream;
setup.max_bit_len = sizeof(bitstream) * CHAR_BIT;
stream_len = 0;
data = 0; model = 0;
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(2, stream_len);
TEST_ASSERT_EQUAL_HEX(0x80000000, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
data = 5; model = 0;
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(14, stream_len);
TEST_ASSERT_EQUAL_HEX(0xBFF80000, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
data = 2; model = 7;
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(25, stream_len);
TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
/* zero escape mechanism */
data = 100; model = 42;
/* (100-42)*2+1=117 -> cw 0 + 0x0000_0000_0000_0075 */
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(58, stream_len);
TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
/* test overflow */
data = INT32_MIN; model = 0;
/* (INT32_MIN)*-2-1+1=0(overflow) -> cw 0 + 0x0000_0000_0000_0000 */
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(91, stream_len);
TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
/* small buffer error */
data = 23; model = 26;
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
/* reset bitstream to all bits set */
bitstream[0] = ~0U;
bitstream[1] = ~0U;
bitstream[2] = ~0U;
stream_len = 0;
/* we use now values with maximum 6 bits */
setup.max_value_bits = 6;
/* lowest value before zero encoding */
data = 53; model = 38;
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(32, stream_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
/* lowest value with zero encoding */
data = 0; model = 16;
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(39, stream_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0x41FFFFFF, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
/* maximum positive value to encode */
data = 31; model = 0;
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(46, stream_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0x40FFFFFF, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
/* maximum negative value to encode */
data = -32U; model = 0;
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(53, stream_len);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0x40FC07FF, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
/* small buffer error when creating the zero escape symbol*/
bitstream[0] = 0;
bitstream[1] = 0;
bitstream[2] = 0;
stream_len = 32;
setup.max_bit_len = 32;
data = 31; model = 0;
stream_len = encode_value_zero(data, model, stream_len, &setup);
TEST_ASSERT_EQUAL_INT(-2, stream_len);
TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment