-CFLAGS = -Isrc -g -Wall -Wextra -Wconversion
+CFLAGS = -Isrc -g -Wall -Wextra -Wconversion -fsanitize=address -fsanitize=undefined
+LDFLAGS = -lasan -lubsan
OBJS = $(patsubst %.c, %.o, $(wildcard src/*.o))
TEST_OBJS = $(patsubst %.c, %.o, $(wildcard test/*.o))
test/test_tans_bit_reader: src/tans_buf_bit_reader.o src/tans_file_bit_reader.o
test/test_tans_bit_writer.o: src/tans_buf_bit_writer.h src/tans_bit_writer.h
test/test_tans_bit_writer: src/tans_buf_bit_writer.o
+test/test_tans_bit_read_write.o: src/tans_buf_bit_writer.h src/tans_bit_writer.h src/tans_rev_buf_bit_reader.h src/tans_bit_reader.h
+test/test_tans_bit_read_write: src/tans_buf_bit_writer.o src/tans_rev_buf_bit_reader.o
test/test_tans_encode_st.o: src/tans_buf_bit_writer.h src/tans_bit_writer.h src/tans_encode_st.h src/tans_symbol_tbl.h src/tans_freq_tbl.h
-test/test_tans_encode_st: src/tans_buf_bit_writer.o src/tans_encode_st.o src/tans_encode_tbl.o src/tans_symbol_tbl.o
+test/test_tans_encode_st: src/tans_buf_bit_writer.o src/tans_encode_st.o src/tans_encode_tbl.o src/tans_symbol_tbl.o src/tans_freq_tbl.o
+test/test_tans_encode_decode.o: src/tans_rev_buf_bit_reader.h src/tans_bit_reader.h src/tans_decode_st.h src/tans_decode_tbl.h src/tans_buf_bit_writer.h src/tans_bit_writer.h src/tans_encode_st.h src/tans_encode_tbl.h src/tans_symbol_tbl.h src/tans_freq_tbl.h
+test/test_tans_encode_decode: src/tans_rev_buf_bit_reader.o src/tans_decode_st.o src/tans_decode_tbl.o src/tans_buf_bit_writer.o src/tans_encode_st.o src/tans_encode_tbl.o src/tans_symbol_tbl.o src/tans_freq_tbl.o
clean:
rm -f $(OBJS)
#pragma once
+#include <stdint.h>
+
static uint16_t floor_log2(uint16_t x)
{
- if (x <= 1) return 0;
- if (x <= 2) return 1;
- if (x <= 4) return 2;
- if (x <= 8) return 3;
- if (x <= 16) return 4;
- if (x <= 32) return 5;
- if (x <= 64) return 6;
- if (x <= 128) return 7;
- if (x <= 256) return 8;
- if (x <= 512) return 9;
- if (x <= 1024) return 10;
- if (x <= 2048) return 11;
- if (x <= 4096) return 12;
- if (x <= 8192) return 13;
- if (x <= 16384) return 14;
- if (x <= 32768) return 15;
- /*if (x <= 65536)*/ return 16;
+ if (x < 2) return 0;
+ if (x < 4) return 1;
+ if (x < 8) return 2;
+ if (x < 16) return 3;
+ if (x < 32) return 4;
+ if (x < 64) return 5;
+ if (x < 128) return 6;
+ if (x < 256) return 7;
+ if (x < 512) return 8;
+ if (x < 1024) return 9;
+ if (x < 2048) return 10;
+ if (x < 4096) return 11;
+ if (x < 8192) return 12;
+ if (x < 16384) return 13;
+ if (x < 32768) return 14;
+ /*if (x < 65536)*/ return 15;
}
uint32_t bit = self->bit % 8;
uint32_t byte = self->bit / 8;
- if (bits == 0 || self->bit + bits > self->len * 8) {
+ if (bits == 0) {
+ return 0;
+ }
+
+ if (self->bit + bits > self->len * 8) {
return (uint16_t) -1;
}
#include "tans_buf_bit_writer.h"
+#include <stdio.h>
+
static uint16_t tans_buf_bit_writer_write(struct tans_bit_writer *writer, uint16_t value, uint8_t bits)
{
struct tans_buf_bit_writer *self = (struct tans_buf_bit_writer *) writer;
return (uint16_t) -1;
}
+ printf("DEBUG: writing bits ");
+ for (uint8_t i = 0; i < bits; i++) {
+ printf(value & (1 << i) ? "1" : "0");
+ }
+ printf("\n");
+
self->bit += bits;
if (bit + bits <= 8) {
#pragma once
-#define TANS_R 10
-#define TANS_L (1 << TANS_R)
+/*
+#define TANS_LOG2_MAX_TBLSZ 10
+#define TANS_MAX_TBLSZ (1 << TANS_LOG2_MAX_TBLSZ)
+#define TANS_MAX_SYMBOLS 256
+*/
+
+#define TANS_LOG2_MAX_TBLSZ 12
+#define TANS_MAX_TBLSZ (1 << TANS_LOG2_MAX_TBLSZ)
+#define TANS_MAX_SYMBOLS 256
#include "tans_decode_st.h"
+#include <stdio.h>
+
void tans_decode_st_init(struct tans_decode_st *self, struct tans_symbol_tbl *symbol_tbl)
{
tans_decode_tbl_init(&self->decode_tbl, symbol_tbl);
uint16_t read;
struct tans_decode_tbl_entry t = self->decode_tbl.entries[self->x];
+ printf("DEBUG: reading %d bits\n", t.nb_bits);
+
read = bit_reader->vtable->read(bit_reader, t.nb_bits);
- if (read == -1) {
- return -1;
+ if (read == (uint16_t) -1) {
+ return (uint16_t) -1;
}
ret = t.symbol;
uint16_t x;
uint8_t s;
- for (i = 0; i < TANS_L; ++i) {
+ self->tblsz = symbol_tbl->tblsz;
+
+ for (i = 0; i < self->tblsz; ++i) {
s = self->entries[i].symbol = symbol_tbl->symbol[i];
x = symbol_tbl->entries[s].next++;
- self->entries[s].nb_bits = TANS_R - floor_log2(x);
- self->entries[s].new_x = (x << self->entries[s].nb_bits) - TANS_L;
+ self->entries[i].nb_bits = (uint8_t) (symbol_tbl->log2_tblsz - floor_log2(x));
+ self->entries[i].new_x = (uint16_t) ((x << self->entries[i].nb_bits) - self->tblsz);
}
}
};
struct tans_decode_tbl {
- struct tans_decode_tbl_entry entries[TANS_L];
+ uint16_t tblsz;
+ struct tans_decode_tbl_entry entries[TANS_MAX_TBLSZ];
};
void tans_decode_tbl_init(struct tans_decode_tbl *self, struct tans_symbol_tbl *symbol_tbl);
#include "tans_encode_st.h"
+#include <stdio.h>
+
void tans_encode_st_init(struct tans_encode_st *self, const struct tans_symbol_tbl *symbol_tbl)
{
self->symbol_tbl = *symbol_tbl;
tans_encode_tbl_init(&self->encode_tbl, &self->symbol_tbl);
- self->x = 0;
+ self->x = self->encode_tbl.tblsz;
}
uint16_t tans_encode_st_next(struct tans_encode_st *self, struct tans_bit_writer *bit_writer, uint8_t symbol)
{
uint8_t nb_bits;
uint16_t written;
+ uint16_t i;
+
+ printf("DEBUG: encoding %02x\n", symbol);
- nb_bits = (uint8_t) ((self->x + TANS_L + self->symbol_tbl.entries[symbol].nb) >> (TANS_R + 1));
- written = bit_writer->vtable->write(bit_writer, self->x + TANS_L, nb_bits);
+ nb_bits = (uint8_t) ((self->x + self->symbol_tbl.entries[symbol].nb) >> (self->symbol_tbl.log2_tblsz + 1));
+ written = bit_writer->vtable->write(bit_writer, self->x, nb_bits);
if (written != nb_bits) {
return (uint16_t) -1;
}
- self->x = self->encode_tbl.entries[self->symbol_tbl.entries[symbol].start + ((self->x + TANS_L) >> nb_bits)].x;
+ i = (uint16_t) (self->symbol_tbl.entries[symbol].start + (self->x >> nb_bits));
+ self->x = self->encode_tbl.entries[i].x;
+
+ printf("DEBUG: moving to state %d\n", self->x);
return written;
}
void tans_encode_tbl_init(struct tans_encode_tbl *self, struct tans_symbol_tbl *symbol_tbl)
{
uint8_t s;
- uint16_t x;
+ uint16_t i, x;
- for (x = TANS_L; x < TANS_L << 1; ++x) {
- s = symbol_tbl->symbol[x-TANS_L];
- self->entries[symbol_tbl->entries[s].start + symbol_tbl->entries[s].next++].x = x - TANS_L;
+ self->tblsz = symbol_tbl->tblsz;
+
+ for (x = self->tblsz; x < self->tblsz << 1; ++x) {
+ s = symbol_tbl->symbol[x-self->tblsz];
+ i = (uint16_t) (symbol_tbl->entries[s].start + symbol_tbl->entries[s].next++);
+ self->entries[i].x = x;
}
}
};
struct tans_encode_tbl {
- // TODO verify size of entries table
- struct tans_encode_tbl_entry entries[TANS_L];
+ uint16_t tblsz;
+ struct tans_encode_tbl_entry entries[TANS_MAX_TBLSZ];
};
void tans_encode_tbl_init(struct tans_encode_tbl *self, struct tans_symbol_tbl *symbol_tbl);
uint32_t byte = self->bit / 8;
if (bits == 0) {
- return (uint16_t) -1;
+ return 0;
}
while (self->len * 8 - self->bit < bits) {
--- /dev/null
+#include "tans_freq_tbl.h"
+
+#include <stdio.h>
+
+int tans_freq_tbl_init(struct tans_freq_tbl *self, uint16_t n_symbols, double *p, uint16_t log2_tblsz)
+{
+ uint16_t i, tblsz, total;
+ double total_p;
+
+ if (n_symbols == 0) return -1;
+ if (n_symbols > TANS_MAX_SYMBOLS) return -1;
+ if (log2_tblsz > TANS_LOG2_MAX_TBLSZ) return -1;
+
+ self->n_symbols = n_symbols;
+ self->log2_tblsz = log2_tblsz;
+ tblsz = 1 << log2_tblsz;
+
+ if (tblsz < n_symbols) return -1;
+
+ total_p = 0.0;
+ for (i = 0; i < n_symbols; ++i) {
+ total_p += p[i];
+ }
+
+ total = 0;
+ for (i = 0; i < n_symbols; ++i) {
+ self->freq[i] = (uint16_t) ((p[i] / total_p + 0.5 / tblsz) * tblsz);
+ if (self->freq[i] == 0) ++self->freq[i];
+ total += self->freq[i];
+ }
+
+ while (total < tblsz) {
+ for (i = 0; i < n_symbols && total < tblsz; ++i) {
+ ++self->freq[i];
+ ++total;
+ }
+ }
+
+ while (total > tblsz) {
+ for (i = 0; i < n_symbols && total > tblsz; ++i) {
+ if (self->freq[i] > 1) {
+ --self->freq[i];
+ --total;
+ }
+ }
+ }
+
+ return 0;
+}
#pragma once
+#include "tans_constants.h"
+
#include <stdint.h>
struct tans_freq_tbl {
- uint16_t freq[256];
+ uint16_t n_symbols;
+ uint16_t log2_tblsz;
+ uint16_t freq[TANS_MAX_SYMBOLS];
};
+
+int tans_freq_tbl_init(struct tans_freq_tbl *self, uint16_t n_symbols, double *p, uint16_t log2_tblsz);
--- /dev/null
+#include "tans_rev_buf_bit_reader.h"
+
+static uint16_t tans_rev_buf_bit_reader_read(struct tans_bit_reader *reader, uint8_t bits)
+{
+ struct tans_rev_buf_bit_reader *self = (struct tans_rev_buf_bit_reader *) reader;
+ uint32_t bit = self->bit % 8 + (uint32_t) 8 * (self->bit % 8 == 0);
+ uint32_t byte = (self->bit - 1) / 8;
+
+ if (bits == 0) {
+ return 0;
+ }
+
+ if (self->bit < bits) {
+ return (uint16_t) -1;
+ }
+
+ self->bit -= bits;
+
+ if (8 - bit + bits <= 8) {
+ return (uint16_t) (((1 << bits) - 1) & (self->buf[byte] >> (bit - bits)));
+ } else if (8 - bit + bits <= 16) {
+ return (uint16_t) (((1 << bits) - 1) & ((self->buf[byte-1] | (self->buf[byte] << 8)) >> (bit + 8 - bits)));
+ } else if (8 - bit + bits <= 24) {
+ return (uint16_t) (((1 << bits) - 1) & ((self->buf[byte-2] | (self->buf[byte-1] << 8) | (self->buf[byte] << 16)) >> (bit + 16 - bits)));
+ } else {
+ return (uint16_t) -1;
+ }
+}
+
+static const struct tans_bit_reader_ops vtable = {
+ .read = tans_rev_buf_bit_reader_read,
+};
+
+void tans_rev_buf_bit_reader_init(struct tans_rev_buf_bit_reader *self, const uint8_t *buf, uint32_t len)
+{
+ self->vtable = &vtable;
+ self->bit = len * 8;
+ self->len = len;
+ self->buf = buf;
+}
--- /dev/null
+#pragma once
+
+#include "tans_bit_reader.h"
+
+struct tans_rev_buf_bit_reader {
+ const struct tans_bit_reader_ops *vtable;
+ uint32_t bit;
+ uint32_t len;
+ const uint8_t *buf;
+};
+
+void tans_rev_buf_bit_reader_init(struct tans_rev_buf_bit_reader *self, const uint8_t *buf, uint32_t len);
{
uint16_t x, step, s, i, start, freq, k;
+ self->n_symbols = freq_tbl->n_symbols;
+ self->log2_tblsz = freq_tbl->log2_tblsz;
+ self->tblsz = 1 << self->log2_tblsz;
+
x = 0;
- step = TANS_L*5/8 + 3;
+ step = (uint16_t) (self->tblsz * 5 / 8 + 3);
start = 0;
- for (s = 0; s < 256; ++s) {
+ for (s = 0; s < self->n_symbols; ++s) {
freq = freq_tbl->freq[s];
- self->entries[s].start = start;
+ self->entries[s].start = start - freq;
self->entries[s].next = freq;
- k = TANS_R - floor_log2(freq);
- self->entries[s].nb = (uint16_t) ((k << (TANS_R + 1)) - (freq << k));
+ k = self->log2_tblsz - floor_log2(freq);
+ self->entries[s].nb = (uint32_t) ((k << (self->log2_tblsz + 1)) - (freq << k));
start += freq;
for (i = 0; i < freq; ++i) {
self->symbol[x] = (uint8_t) s;
x += step;
- x %= TANS_L;
+ x &= self->tblsz - 1;
}
}
- if (start != TANS_L) { // freq entries must add up to TANS_L
+ if (start != self->tblsz) { // freq entries must add up to tblsz
return -1;
}
#include "tans_freq_tbl.h"
struct tans_symbol_tbl_entry {
- uint16_t nb;
+ uint32_t nb;
uint16_t start;
uint16_t next;
};
struct tans_symbol_tbl {
- uint8_t symbol[TANS_L];
- struct tans_symbol_tbl_entry entries[256];
+ uint16_t n_symbols;
+ uint16_t log2_tblsz;
+ uint16_t tblsz;
+ uint8_t symbol[TANS_MAX_TBLSZ];
+ struct tans_symbol_tbl_entry entries[TANS_MAX_SYMBOLS];
};
int tans_symbol_tbl_init(struct tans_symbol_tbl *self, const struct tans_freq_tbl *freq_tbl);
#define ASSERT_EQ(lhs, rhs) do { \
long a = (long) (lhs), b = (long) (rhs); \
if ((a) != (b)) { \
- printf("ERROR: " #lhs " (%ld) != " #rhs " (%ld)\n", (a), (b)); \
+ printf("ERROR: %s:%d: %s (%ld) != %s (%ld)\n", __FILE__, __LINE__, #lhs, a, #rhs, b); \
return TEST_FAILURE; \
} \
} while(0)
#define ASSERT_NE(lhs, rhs) do { \
long a = (long) (lhs), b = (long) (rhs); \
if ((a) == (b)) { \
- printf("ERROR: " #lhs " (%ld) == " #rhs " (%ld)\n", (a), (b)); \
+ printf("ERROR: %s:%d: %s (%ld) == %s (%ld)\n", __FILE__, __LINE__, #lhs, a, #rhs, b); \
+ return TEST_FAILURE; \
+ } \
+ } while(0)
+
+#define ASSERT_LT(lhs, rhs) do { \
+ long a = (long) (lhs), b = (long) (rhs); \
+ if ((a) >= (b)) { \
+ printf("ERROR: %s:%d: %s (%ld) >= %s (%ld)\n", __FILE__, __LINE__, #lhs, a, #rhs, b); \
return TEST_FAILURE; \
} \
} while(0)
--- /dev/null
+#include "test.h"
+
+#include "tans_buf_bit_writer.h"
+#include "tans_rev_buf_bit_reader.h"
+
+enum test_result test_tans_buf_bit_write_read_rev(void)
+{
+ struct tans_buf_bit_writer buf_bit_writer;
+ struct tans_bit_writer *bit_writer = (struct tans_bit_writer *) &buf_bit_writer;
+ struct tans_rev_buf_bit_reader buf_bit_reader;
+ struct tans_bit_reader *bit_reader = (struct tans_bit_reader *) &buf_bit_reader;
+ uint8_t buf[8] = {0};
+
+ tans_buf_bit_writer_init(&buf_bit_writer, buf, sizeof buf);
+ tans_rev_buf_bit_reader_init(&buf_bit_reader, buf, sizeof buf);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0, 0), 0);
+
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 1, 8), 8);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0xf, 4), 4);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0x2f, 6), 6);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0, 2), 2);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0x3fe0, 16), 16);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0xd0, 8), 8);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0x0f, 7), 7);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 1, 1), 1);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0, 3), 3);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0x18, 5), 5);
+ ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0xf, 4), 4);
+
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 4), 0xf);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 5), 0x18);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 3), 0);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 1), 1);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 7), 0x0f);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 8), 0xd0);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 16), 0x3fe0);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 2), 0);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 6), 0x2f);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 4), 0xf);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 8), 1);
+
+ return TEST_SUCCESS;
+}
+
+int main(void)
+{
+ RUN_TEST(test_tans_buf_bit_write_read_rev);
+}
enum test_result test_tans_buf_bit_reader(void)
{
- struct tans_buf_bit_reader bit_reader;
+ struct tans_buf_bit_reader buf_bit_reader;
+ struct tans_bit_reader *bit_reader = (struct tans_bit_reader *) &buf_bit_reader;
uint8_t buf[8] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0xfd, 0x08, 0xfc};
- tans_buf_bit_reader_init(&bit_reader, buf, sizeof buf);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 0), (uint16_t) -1);
-
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 8), 1);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 4), 0xf);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 6), 0x2f);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 2), 0);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 16), 0x3fe0);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 8), 0xd0);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 7), 0x0f);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 1), 1);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 3), 0);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 5), 0x18);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 4), 0xf);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 1), (uint16_t) -1);
+ tans_buf_bit_reader_init(&buf_bit_reader, buf, sizeof buf);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 0), 0);
+
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 8), 1);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 4), 0xf);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 6), 0x2f);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 2), 0);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 16), 0x3fe0);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 8), 0xd0);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 7), 0x0f);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 1), 1);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 3), 0);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 5), 0x18);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 4), 0xf);
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, 1), (uint16_t) -1);
return TEST_SUCCESS;
}
enum test_result test_tans_file_bit_reader(void)
{
- struct tans_file_bit_reader bit_reader;
+ struct tans_file_bit_reader file_bit_reader;
+ struct tans_bit_reader *bit_reader = (struct tans_bit_reader *) &file_bit_reader;
uint8_t bits;
- ASSERT_EQ(tans_file_bit_reader_init(&bit_reader, "/dev/zero"), 0);
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 0), (uint16_t) -1);
+ ASSERT_EQ(tans_file_bit_reader_init(&file_bit_reader, "/dev/zero"), 0);
- for (bits = 1; bits <= 16; ++bits) {
- ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, bits), 0);
+ for (bits = 0; bits <= 16; ++bits) {
+ ASSERT_EQ(bit_reader->vtable->read(bit_reader, bits), 0);
}
return TEST_SUCCESS;
--- /dev/null
+#include "test.h"
+
+#include "floor_log2.h"
+#include "tans_buf_bit_writer.h"
+#include "tans_decode_st.h"
+#include "tans_encode_st.h"
+#include "tans_rev_buf_bit_reader.h"
+
+enum test_result test_tans_encode_decode_equal_freq(void)
+{
+ struct tans_freq_tbl freq_tbl;
+ struct tans_symbol_tbl symbol_tbl;
+ struct tans_encode_st encode_st;
+ struct tans_buf_bit_writer buf_bit_writer;
+ struct tans_bit_writer *bit_writer = (struct tans_bit_writer *) &buf_bit_writer;
+ struct tans_decode_st decode_st;
+ struct tans_rev_buf_bit_reader buf_bit_reader;
+ struct tans_bit_reader *bit_reader = (struct tans_bit_reader *) &buf_bit_reader;
+ uint8_t data[8] = {0x01, 0xfe, 0x32, 0x12, 0x06, 0x07, 0x88, 0x00};
+ double p[256];
+ uint8_t buf[8] = {0};
+ uint16_t i;
+ uint16_t n_symbols = 256;
+ uint16_t log2_tblsz = 10;
+
+ for (i = 0; i < n_symbols; ++i) p[i] = 1.0 / n_symbols;
+ ASSERT_NE(tans_freq_tbl_init(&freq_tbl, n_symbols, p, log2_tblsz), -1);
+ ASSERT_EQ(tans_symbol_tbl_init(&symbol_tbl, &freq_tbl), 0);
+ tans_encode_st_init(&encode_st, &symbol_tbl);
+ tans_buf_bit_writer_init(&buf_bit_writer, buf, floor_log2(n_symbols));
+ tans_decode_st_init(&decode_st, &symbol_tbl);
+ tans_rev_buf_bit_reader_init(&buf_bit_reader, buf, floor_log2(n_symbols));
+
+ for (i = 0; i < sizeof data; ++i) {
+ ASSERT_NE(tans_encode_st_next(&encode_st, bit_writer, (uint8_t) (data[i] % n_symbols)), (uint16_t) -1);
+ }
+
+ ASSERT_EQ(buf_bit_writer.bit, buf_bit_writer.len * 8);
+ ASSERT_EQ(buf_bit_writer.bit, buf_bit_reader.bit);
+
+ decode_st.x = (uint16_t) (encode_st.x - (1 << log2_tblsz));
+
+ for (i = 0; i < sizeof data; ++i) {
+ ASSERT_EQ(tans_decode_st_next(&decode_st, bit_reader), data[sizeof data - 1 - i] % n_symbols);
+ }
+
+ return TEST_SUCCESS;
+}
+
+enum test_result test_tans_encode_decode_high_zero_probability(void)
+{
+ struct tans_freq_tbl freq_tbl;
+ struct tans_symbol_tbl symbol_tbl;
+ struct tans_encode_st encode_st;
+ struct tans_buf_bit_writer buf_bit_writer;
+ struct tans_bit_writer *bit_writer = (struct tans_bit_writer *) &buf_bit_writer;
+ struct tans_decode_st decode_st;
+ struct tans_rev_buf_bit_reader buf_bit_reader;
+ struct tans_bit_reader *bit_reader = (struct tans_bit_reader *) &buf_bit_reader;
+ uint8_t data[8] = {0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x23};
+ double p[256];
+ uint8_t buf[8] = {0};
+ uint16_t i;
+ uint16_t n_symbols = 256;
+ uint16_t log2_tblsz = 12;
+
+ p[0] = 0.75;
+ for (i = 1; i < n_symbols; ++i) p[i] = 0.25 / n_symbols;
+ ASSERT_NE(tans_freq_tbl_init(&freq_tbl, n_symbols, p, log2_tblsz), -1);
+ ASSERT_EQ(tans_symbol_tbl_init(&symbol_tbl, &freq_tbl), 0);
+ tans_encode_st_init(&encode_st, &symbol_tbl);
+ tans_buf_bit_writer_init(&buf_bit_writer, buf, floor_log2(n_symbols));
+ tans_decode_st_init(&decode_st, &symbol_tbl);
+ tans_rev_buf_bit_reader_init(&buf_bit_reader, buf, floor_log2(n_symbols));
+
+ for (i = 0; i < sizeof data; ++i) {
+ ASSERT_NE(tans_encode_st_next(&encode_st, bit_writer, (uint8_t) (data[i] % n_symbols)), (uint16_t) -1);
+ }
+
+ buf_bit_reader.bit = buf_bit_writer.bit;
+ decode_st.x = (uint16_t) (encode_st.x - (1 << log2_tblsz));
+
+ for (i = 0; i < sizeof data; ++i) {
+ ASSERT_EQ(tans_decode_st_next(&decode_st, bit_reader), data[sizeof data - 1 - i] % n_symbols);
+ }
+
+ return TEST_SUCCESS;
+}
+
+enum test_result test_tans_encode_decode_long_stream(void)
+{
+ struct tans_freq_tbl freq_tbl;
+ struct tans_symbol_tbl symbol_tbl;
+ struct tans_encode_st encode_st;
+ struct tans_buf_bit_writer buf_bit_writer;
+ struct tans_bit_writer *bit_writer = (struct tans_bit_writer *) &buf_bit_writer;
+ struct tans_decode_st decode_st;
+ struct tans_rev_buf_bit_reader buf_bit_reader;
+ struct tans_bit_reader *bit_reader = (struct tans_bit_reader *) &buf_bit_reader;
+ uint8_t data[65536];
+ double p[256];
+ uint8_t buf[32768] = {0};
+ uint16_t n_symbols = 256;
+ uint16_t log2_tblsz = 10;
+ uint32_t i;
+
+ p[0] = 0.75;
+ for (i = 1; i < n_symbols; ++i) p[i] = 0.25 / n_symbols;
+ ASSERT_NE(tans_freq_tbl_init(&freq_tbl, n_symbols, p, log2_tblsz), -1);
+ ASSERT_EQ(tans_symbol_tbl_init(&symbol_tbl, &freq_tbl), 0);
+ tans_encode_st_init(&encode_st, &symbol_tbl);
+ tans_buf_bit_writer_init(&buf_bit_writer, buf, sizeof buf);
+ tans_decode_st_init(&decode_st, &symbol_tbl);
+ tans_rev_buf_bit_reader_init(&buf_bit_reader, buf, sizeof buf);
+
+ for (i = 0; i < 65536; ++i) {
+ data[i] = (uint8_t) (i % 4 == 3 ? i / 4 : 0);
+ }
+
+ for (i = 0; i < sizeof data; ++i) {
+ ASSERT_NE(tans_encode_st_next(&encode_st, bit_writer, (uint8_t) (data[i] % n_symbols)), (uint16_t) -1);
+ }
+
+ buf_bit_reader.bit = buf_bit_writer.bit;
+ decode_st.x = (uint16_t) (encode_st.x - (1 << log2_tblsz));
+
+ for (i = 0; i < sizeof data; ++i) {
+ ASSERT_EQ(tans_decode_st_next(&decode_st, bit_reader), data[sizeof data - 1 - i] % n_symbols);
+ }
+
+ return TEST_SUCCESS;
+}
+
+int main(void)
+{
+ RUN_TEST(test_tans_encode_decode_equal_freq);
+ RUN_TEST(test_tans_encode_decode_high_zero_probability);
+ RUN_TEST(test_tans_encode_decode_long_stream);
+}
#include "test.h"
+#include "floor_log2.h"
#include "tans_buf_bit_writer.h"
#include "tans_encode_st.h"
struct tans_encode_st encode_st;
struct tans_buf_bit_writer buf_bit_writer;
struct tans_bit_writer *bit_writer = (struct tans_bit_writer *) &buf_bit_writer;
- uint8_t data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
+ uint8_t data[8] = {0x01, 0xfe, 0x32, 0x12, 0x06, 0x07, 0x88, 0x00};
+ double p[256];
uint8_t buf[8] = {0};
uint16_t i;
+ uint16_t n_symbols = 256;
+ uint16_t log2_tblsz = 10;
- for (i = 0; i < 256; ++i) {
- freq_tbl.freq[i] = TANS_L / 256;
- }
+ for (i = 0; i < n_symbols; ++i) p[i] = 1.0 / n_symbols;
+ ASSERT_NE(tans_freq_tbl_init(&freq_tbl, n_symbols, p, log2_tblsz), -1);
ASSERT_EQ(tans_symbol_tbl_init(&symbol_tbl, &freq_tbl), 0);
tans_encode_st_init(&encode_st, &symbol_tbl);
- tans_buf_bit_writer_init(&buf_bit_writer, buf, sizeof buf);
+ tans_buf_bit_writer_init(&buf_bit_writer, buf, floor_log2(n_symbols));
for (i = 0; i < sizeof data; ++i) {
- ASSERT_NE(tans_encode_st_next(&encode_st, bit_writer, data[i]), (uint16_t) -1);
+ ASSERT_NE(tans_encode_st_next(&encode_st, bit_writer, (uint8_t) (data[i] % n_symbols)), (uint16_t) -1);
}
ASSERT_EQ(buf_bit_writer.bit, buf_bit_writer.len * 8);
return TEST_SUCCESS;
}
+enum test_result test_tans_encode_st_high_zero_probability(void)
+{
+ struct tans_freq_tbl freq_tbl;
+ struct tans_symbol_tbl symbol_tbl;
+ struct tans_encode_st encode_st;
+ struct tans_buf_bit_writer buf_bit_writer;
+ struct tans_bit_writer *bit_writer = (struct tans_bit_writer *) &buf_bit_writer;
+ uint8_t data[8] = {0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x23};
+ double p[256];
+ uint8_t buf[16] = {0};
+ uint16_t i;
+ uint16_t n_symbols = 256;
+ uint16_t log2_tblsz = 12;
+
+ p[0] = 0.75;
+ for (i = 1; i < n_symbols; ++i) p[i] = 0.25 / n_symbols;
+ ASSERT_NE(tans_freq_tbl_init(&freq_tbl, n_symbols, p, log2_tblsz), -1);
+ ASSERT_EQ(tans_symbol_tbl_init(&symbol_tbl, &freq_tbl), 0);
+ tans_encode_st_init(&encode_st, &symbol_tbl);
+ tans_buf_bit_writer_init(&buf_bit_writer, buf, sizeof buf);
+
+ for (i = 0; i < sizeof data; ++i) {
+ ASSERT_NE(tans_encode_st_next(&encode_st, bit_writer, (uint8_t) (data[i] % n_symbols)), (uint16_t) -1);
+ }
+
+ ASSERT_LT(buf_bit_writer.bit, 24);
+
+ return TEST_SUCCESS;
+}
+
int main(void)
{
RUN_TEST(test_tans_encode_st_equal_freq);
+ RUN_TEST(test_tans_encode_st_high_zero_probability);
}