Commit 8ee20f33 authored by Mathis Rosenhauer's avatar Mathis Rosenhauer

fix signed handling

parent 082c9c46
......@@ -43,6 +43,9 @@ check: encode decode test_szcomp
./encode -c -b4 -B32 -R128 -J8 ../data/example_data > ../data/test.aee
./decode -b4 -B32 -R128 -J8 ../data/test.aee
cmp ../data/test ../data/example_data
./encode -c -s -b4 -B32 -R128 -J8 ../data/example_data > ../data/test.aee
./decode -s -b4 -B32 -R128 -J8 ../data/test.aee
cmp ../data/test ../data/example_data
./encode -c -b 512 -B8 -R128 -J8 ../data/example_data > ../data/test.aee
./decode -b 512 -B8 -R128 -J8 ../data/test.aee
cmp ../data/test ../data/example_data
......
......@@ -119,30 +119,39 @@ static void put_8(ae_streamp strm, int64_t data)
static inline void u_put(ae_streamp strm, int64_t sample)
{
int64_t x, d, th, D;
decode_state *state;
int64_t x, d, th, D, lower;
decode_state *state = strm->state;
state = strm->state;
if (state->pp && (state->samples_out % state->ref_int != 0))
{
d = sample;
x = state->last_out;
th = MIN(x - state->xmin, state->xmax - x);
lower = x - state->xmin;
th = MIN(lower, state->xmax - x);
if (d <= 2*th)
if (d <= 2 * th)
{
if (d & 1)
D = - (d + 1) / 2;
else
D = d / 2;
} else {
if (th == x)
if (th == lower)
D = d - th;
else
D = th - d;
}
sample = x + D;
}
else
{
if (strm->flags & AE_DATA_SIGNED)
{
int m = 64 - strm->bit_per_sample;
/* Reference samples have to be sign extended */
sample = (sample << m) >> m;
}
}
state->last_out = sample;
state->put_sample(strm, sample);
state->samples_out++;
......
......@@ -88,56 +88,97 @@ static inline void emitfs(encode_state *state, int fs)
}
}
static inline void emitblock(ae_streamp strm, int k, int skip)
#define EMITBLOCK(ref) \
static inline void emitblock_##ref(ae_streamp strm, int k) \
{ \
int b; \
uint64_t a; \
encode_state *state = strm->state; \
uint32_t *in = state->block_p + ref; \
uint32_t *in_end = state->block_p + strm->block_size; \
uint64_t mask = (1ULL << k) - 1; \
uint8_t *o = state->cds_p; \
int p = state->bit_p; \
\
a = *o; \
\
while(in < in_end) \
{ \
a <<= 56; \
p = (p % 8) + 56; \
\
while (p > k && in < in_end) \
{ \
p -= k; \
a += ((uint64_t)(*in++) & mask) << p; \
} \
\
for (b = 56; b > (p & ~7); b -= 8) \
*o++ = a >> b; \
a >>= b; \
} \
\
*o = a; \
state->cds_p = o; \
state->bit_p = p % 8; \
}
EMITBLOCK(0);
EMITBLOCK(1);
static void preprocess_unsigned(ae_streamp strm)
{
int i;
uint64_t acc;
int64_t theta, Delta, prev;
encode_state *state = strm->state;
uint32_t *in = state->block_p + skip;
uint32_t *in_end = state->block_p + strm->block_size;
uint64_t mask = (1ULL << k) - 1;
uint8_t *out = state->cds_p;
acc = *out;
/* Insert reference samples into first block of Reference Sample
* Interval.
*/
prev = state->block_buf[0];
while(in < in_end)
for (i = 1; i < strm->rsi * strm->block_size; i++)
{
acc <<= 56;
state->bit_p = (state->bit_p % 8) + 56;
theta = MIN(prev, state->xmax - prev);
Delta = (int64_t)state->block_buf[i] - prev;
prev = state->block_buf[i];
while (state->bit_p > k && in < in_end)
if (0 <= Delta && Delta <= theta)
{
state->bit_p -= k;
acc += ((uint64_t)(*in++) & mask) << state->bit_p;
state->block_buf[i] = 2 * Delta;
}
else if (-theta <= Delta && Delta < 0)
{
state->block_buf[i] = 2
* (Delta < 0 ? -(uint64_t)Delta : Delta) - 1;
}
else
{
state->block_buf[i] = theta
+ (Delta < 0 ? -(uint64_t)Delta : Delta);
}
for (i = 56; i > (state->bit_p & ~7); i -= 8)
*out++ = acc >> i;
acc >>= i;
}
*out = acc;
state->cds_p = out;
state->bit_p %= 8;
}
static inline void preprocess(ae_streamp strm)
static void preprocess_signed(ae_streamp strm)
{
int i;
int64_t theta, Delta, last_in;
int i, m;
int64_t theta, Delta, prev, sample;
encode_state *state = strm->state;
/* Insert reference samples into first block of Reference Sample
* Interval.
*/
last_in = state->block_buf[0];
m = 64 - strm->bit_per_sample;
prev = ((int64_t)state->block_buf[0] << m) >> m;
for (i = 1; i < strm->rsi * strm->block_size; i++)
{
theta = MIN(last_in - state->xmin,
state->xmax - last_in);
Delta = (int64_t)state->block_buf[i] - last_in;
last_in = state->block_buf[i];
theta = MIN(prev - state->xmin, state->xmax - prev);
sample = ((int64_t)state->block_buf[i] << m) >> m;
Delta = sample - prev;
prev = sample;
if (0 <= Delta && Delta <= theta)
{
state->block_buf[i] = 2 * Delta;
......@@ -196,7 +237,7 @@ static int m_get_block(ae_streamp strm)
state->get_block(strm);
if (strm->flags & AE_DATA_PREPROCESS)
preprocess(strm);
state->preprocess(strm);
return m_check_zero_block(strm);
}
......@@ -270,7 +311,7 @@ static int m_get_block_cautious(ae_streamp strm)
while (++state->i < strm->rsi * strm->block_size);
if (strm->flags & AE_DATA_PREPROCESS)
preprocess(strm);
state->preprocess(strm);
return m_check_zero_block(strm);
}
......@@ -323,16 +364,16 @@ static inline int m_check_zero_block(ae_streamp strm)
static inline int m_select_code_option(ae_streamp strm)
{
int i, j, k, this_bs, looked_bothways, direction;
int64_t split_len, uncomp_len;
int64_t split_len_min, fs_len;
int64_t d, se_len;
uint64_t split_len, uncomp_len;
uint64_t split_len_min, fs_len;
uint64_t d, se_len;
encode_state *state = strm->state;
/* Length of this block minus reference sample (if present) */
this_bs = strm->block_size - state->ref;
split_len_min = INT64_MAX;
i = state->k;
split_len_min = UINT64_MAX;
i = k = state->k;
direction = 1;
looked_bothways = 0;
......@@ -341,26 +382,26 @@ static inline int m_select_code_option(ae_streamp strm)
*/
for (;;)
{
fs_len = (int64_t)(state->block_p[1] >> i)
+ (int64_t)(state->block_p[2] >> i)
+ (int64_t)(state->block_p[3] >> i)
+ (int64_t)(state->block_p[4] >> i)
+ (int64_t)(state->block_p[5] >> i)
+ (int64_t)(state->block_p[6] >> i)
+ (int64_t)(state->block_p[7] >> i);
fs_len = (uint64_t)(state->block_p[1] >> i)
+ (uint64_t)(state->block_p[2] >> i)
+ (uint64_t)(state->block_p[3] >> i)
+ (uint64_t)(state->block_p[4] >> i)
+ (uint64_t)(state->block_p[5] >> i)
+ (uint64_t)(state->block_p[6] >> i)
+ (uint64_t)(state->block_p[7] >> i);
if (state->ref == 0)
fs_len += (int64_t)(state->block_p[0] >> i);
fs_len += (uint64_t)(state->block_p[0] >> i);
if (strm->block_size > 8)
for (j = 8; j < strm->block_size; j++)
fs_len += (int64_t)(state->block_p[j] >> i);
fs_len += (uint64_t)(state->block_p[j] >> i);
split_len = fs_len + this_bs * (i + 1);
if (split_len < split_len_min)
{
if (split_len_min < INT64_MAX)
if (split_len_min < UINT64_MAX)
{
/* We are moving towards the minimum so it cant be in
* the other direction.
......@@ -442,16 +483,17 @@ static inline int m_select_code_option(ae_streamp strm)
se_len = 1;
for (i = 0; i < strm->block_size; i+= 2)
{
d = (int64_t)state->block_p[i] + (int64_t)state->block_p[i + 1];
d = (uint64_t)state->block_p[i]
+ (uint64_t)state->block_p[i + 1];
/* we have to worry about overflow here */
if (d > split_len_min)
{
se_len = INT64_MAX;
se_len = UINT64_MAX;
break;
}
else
{
se_len += d * (d + 1) / 2 + (int64_t)state->block_p[i + 1];
se_len += d * (d + 1) / 2 + (uint64_t)state->block_p[i + 1];
}
}
......@@ -493,13 +535,18 @@ static inline int m_encode_splitting(ae_streamp strm)
emit(state, k + 1, state->id_len);
if (state->ref)
{
emit(state, state->block_p[0], strm->bit_per_sample);
for (i = state->ref; i < strm->block_size; i++)
emitfs(state, state->block_p[i] >> k);
if (k)
emitblock(strm, k, state->ref);
for (i = 1; i < strm->block_size; i++)
emitfs(state, state->block_p[i] >> k);
if (k) emitblock_1(strm, k);
}
else
{
for (i = 0; i < strm->block_size; i++)
emitfs(state, state->block_p[i] >> k);
if (k) emitblock_0(strm, k);
}
return m_flush_block(strm);
}
......@@ -509,7 +556,7 @@ static inline int m_encode_uncomp(ae_streamp strm)
encode_state *state = strm->state;
emit(state, (1 << state->id_len) - 1, state->id_len);
emitblock(strm, strm->bit_per_sample, 0);
emitblock_0(strm, strm->bit_per_sample);
return m_flush_block(strm);
}
......@@ -674,11 +721,13 @@ int ae_encode_init(ae_streamp strm)
{
state->xmin = -(1ULL << (strm->bit_per_sample - 1));
state->xmax = (1ULL << (strm->bit_per_sample - 1)) - 1;
state->preprocess = preprocess_signed;
}
else
{
state->xmin = 0;
state->xmax = (1ULL << strm->bit_per_sample) - 1;
state->preprocess = preprocess_unsigned;
}
state->block_buf = (uint32_t *)malloc(strm->rsi
......
......@@ -11,6 +11,7 @@ typedef struct internal_state {
int (*mode)(ae_streamp);
void (*get_block)(ae_streamp);
uint32_t (*get_sample)(ae_streamp);
void (*preprocess)(ae_streamp);
int id_len; /* bit length of code option identification key */
int64_t xmin; /* minimum integer for preprocessing */
......
......@@ -27,7 +27,7 @@ int main(int argc, char *argv[])
strm.flags = AE_DATA_MSB | AE_DATA_PREPROCESS;
opterr = 0;
while ((c = getopt (argc, argv, "cb:B:J:R:")) != -1)
while ((c = getopt (argc, argv, "scb:B:J:R:")) != -1)
switch (c)
{
case 'b':
......@@ -45,6 +45,9 @@ int main(int argc, char *argv[])
case 'c':
cflag = 1;
break;
case 's':
strm.flags |= AE_DATA_SIGNED;
break;
case '?':
if (optopt == 'b')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
......
......@@ -27,7 +27,7 @@ int main(int argc, char *argv[])
strm.flags = AE_DATA_MSB | AE_DATA_PREPROCESS;
opterr = 0;
while ((c = getopt (argc, argv, "cb:B:R:J:")) != -1)
while ((c = getopt (argc, argv, "scb:B:R:J:")) != -1)
switch (c)
{
case 'b':
......@@ -45,6 +45,9 @@ int main(int argc, char *argv[])
case 'c':
cflag = 1;
break;
case 's':
strm.flags |= AE_DATA_SIGNED;
break;
case '?':
if (optopt == 'b')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment