From 70e2a49d7aa92a2b7786a959b31fb02aa9b489a5 Mon Sep 17 00:00:00 2001 From: Geoffrey Allott Date: Sun, 31 Jul 2022 20:27:53 +0100 Subject: [PATCH] initial implementation complete --- Makefile | 9 ++- src/floor_log2.h | 35 ++++---- src/tans_buf_bit_reader.c | 6 +- src/tans_buf_bit_writer.c | 8 ++ src/tans_constants.h | 11 ++- src/tans_decode_st.c | 8 +- src/tans_decode_tbl.c | 8 +- src/tans_decode_tbl.h | 3 +- src/tans_encode_st.c | 16 +++- src/tans_encode_tbl.c | 11 ++- src/tans_encode_tbl.h | 4 +- src/tans_file_bit_reader.c | 2 +- src/tans_freq_tbl.c | 49 +++++++++++ src/tans_freq_tbl.h | 8 +- src/tans_rev_buf_bit_reader.c | 40 +++++++++ src/tans_rev_buf_bit_reader.h | 12 +++ src/tans_symbol_tbl.c | 18 +++-- src/tans_symbol_tbl.h | 9 ++- test/test.h | 12 ++- test/test_tans_bit_read_write.c | 48 +++++++++++ test/test_tans_bit_reader | Bin 27064 -> 0 bytes test/test_tans_bit_reader.c | 43 +++++----- test/test_tans_bit_writer | Bin 25016 -> 0 bytes test/test_tans_encode_decode.c | 139 ++++++++++++++++++++++++++++++++ test/test_tans_encode_st | Bin 28912 -> 0 bytes test/test_tans_encode_st.c | 46 +++++++++-- 26 files changed, 466 insertions(+), 79 deletions(-) create mode 100644 src/tans_freq_tbl.c create mode 100644 src/tans_rev_buf_bit_reader.c create mode 100644 src/tans_rev_buf_bit_reader.h create mode 100644 test/test_tans_bit_read_write.c delete mode 100755 test/test_tans_bit_reader delete mode 100755 test/test_tans_bit_writer create mode 100644 test/test_tans_encode_decode.c delete mode 100755 test/test_tans_encode_st diff --git a/Makefile b/Makefile index cedffbd..2a5b509 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ -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)) @@ -19,8 +20,12 @@ test/test_tans_bit_reader.o: src/tans_buf_bit_reader.h src/tans_file_bit_reader. 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) diff --git a/src/floor_log2.h b/src/floor_log2.h index 24c2e0e..64e1e0b 100644 --- a/src/floor_log2.h +++ b/src/floor_log2.h @@ -1,22 +1,23 @@ #pragma once +#include + 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; } diff --git a/src/tans_buf_bit_reader.c b/src/tans_buf_bit_reader.c index 564549e..e120ee0 100644 --- a/src/tans_buf_bit_reader.c +++ b/src/tans_buf_bit_reader.c @@ -6,7 +6,11 @@ static uint16_t tans_buf_bit_reader_read(struct tans_bit_reader *reader, uint8_t 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; } diff --git a/src/tans_buf_bit_writer.c b/src/tans_buf_bit_writer.c index 20186a1..0d36ecd 100644 --- a/src/tans_buf_bit_writer.c +++ b/src/tans_buf_bit_writer.c @@ -1,5 +1,7 @@ #include "tans_buf_bit_writer.h" +#include + 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; @@ -14,6 +16,12 @@ static uint16_t tans_buf_bit_writer_write(struct tans_bit_writer *writer, uint16 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) { diff --git a/src/tans_constants.h b/src/tans_constants.h index ea031f2..16a816f 100644 --- a/src/tans_constants.h +++ b/src/tans_constants.h @@ -1,4 +1,11 @@ #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 diff --git a/src/tans_decode_st.c b/src/tans_decode_st.c index c5077fc..19e6762 100644 --- a/src/tans_decode_st.c +++ b/src/tans_decode_st.c @@ -1,5 +1,7 @@ #include "tans_decode_st.h" +#include + 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); @@ -12,9 +14,11 @@ uint16_t tans_decode_st_next(struct tans_decode_st *self, struct tans_bit_reader 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; diff --git a/src/tans_decode_tbl.c b/src/tans_decode_tbl.c index e3feb24..784ddac 100644 --- a/src/tans_decode_tbl.c +++ b/src/tans_decode_tbl.c @@ -8,10 +8,12 @@ void tans_decode_tbl_init(struct tans_decode_tbl *self, struct tans_symbol_tbl * 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); } } diff --git a/src/tans_decode_tbl.h b/src/tans_decode_tbl.h index e191176..7c374a3 100644 --- a/src/tans_decode_tbl.h +++ b/src/tans_decode_tbl.h @@ -9,7 +9,8 @@ struct tans_decode_tbl_entry { }; 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); diff --git a/src/tans_encode_st.c b/src/tans_encode_st.c index d6c7232..6dc3930 100644 --- a/src/tans_encode_st.c +++ b/src/tans_encode_st.c @@ -1,23 +1,31 @@ #include "tans_encode_st.h" +#include + 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; } diff --git a/src/tans_encode_tbl.c b/src/tans_encode_tbl.c index a60ebdc..6c01b75 100644 --- a/src/tans_encode_tbl.c +++ b/src/tans_encode_tbl.c @@ -3,10 +3,13 @@ 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; } } diff --git a/src/tans_encode_tbl.h b/src/tans_encode_tbl.h index 79ccf30..fbae420 100644 --- a/src/tans_encode_tbl.h +++ b/src/tans_encode_tbl.h @@ -8,8 +8,8 @@ struct tans_encode_tbl_entry { }; 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); diff --git a/src/tans_file_bit_reader.c b/src/tans_file_bit_reader.c index fa79ddd..a84a306 100644 --- a/src/tans_file_bit_reader.c +++ b/src/tans_file_bit_reader.c @@ -12,7 +12,7 @@ static uint16_t tans_file_bit_reader_read(struct tans_bit_reader *reader, uint8_ uint32_t byte = self->bit / 8; if (bits == 0) { - return (uint16_t) -1; + return 0; } while (self->len * 8 - self->bit < bits) { diff --git a/src/tans_freq_tbl.c b/src/tans_freq_tbl.c new file mode 100644 index 0000000..23b88dd --- /dev/null +++ b/src/tans_freq_tbl.c @@ -0,0 +1,49 @@ +#include "tans_freq_tbl.h" + +#include + +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; +} diff --git a/src/tans_freq_tbl.h b/src/tans_freq_tbl.h index d2ff754..168067c 100644 --- a/src/tans_freq_tbl.h +++ b/src/tans_freq_tbl.h @@ -1,7 +1,13 @@ #pragma once +#include "tans_constants.h" + #include 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); diff --git a/src/tans_rev_buf_bit_reader.c b/src/tans_rev_buf_bit_reader.c new file mode 100644 index 0000000..a0fe4a9 --- /dev/null +++ b/src/tans_rev_buf_bit_reader.c @@ -0,0 +1,40 @@ +#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; +} diff --git a/src/tans_rev_buf_bit_reader.h b/src/tans_rev_buf_bit_reader.h new file mode 100644 index 0000000..93f8b2b --- /dev/null +++ b/src/tans_rev_buf_bit_reader.h @@ -0,0 +1,12 @@ +#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); diff --git a/src/tans_symbol_tbl.c b/src/tans_symbol_tbl.c index a1237b9..fe105fd 100644 --- a/src/tans_symbol_tbl.c +++ b/src/tans_symbol_tbl.c @@ -6,25 +6,29 @@ int tans_symbol_tbl_init(struct tans_symbol_tbl *self, const struct tans_freq_tb { 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; } diff --git a/src/tans_symbol_tbl.h b/src/tans_symbol_tbl.h index 985928c..1392b5a 100644 --- a/src/tans_symbol_tbl.h +++ b/src/tans_symbol_tbl.h @@ -4,14 +4,17 @@ #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); diff --git a/test/test.h b/test/test.h index d9888ea..31290bd 100644 --- a/test/test.h +++ b/test/test.h @@ -11,7 +11,7 @@ enum test_result { #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) @@ -19,7 +19,15 @@ enum test_result { #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) diff --git a/test/test_tans_bit_read_write.c b/test/test_tans_bit_read_write.c new file mode 100644 index 0000000..4ce2153 --- /dev/null +++ b/test/test_tans_bit_read_write.c @@ -0,0 +1,48 @@ +#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); +} diff --git a/test/test_tans_bit_reader b/test/test_tans_bit_reader deleted file mode 100755 index 1f43ac2e1d48193b8b27405aa82891ad24f4730f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27064 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 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; diff --git a/test/test_tans_bit_writer b/test/test_tans_bit_writer deleted file mode 100755 index e8fe9ba558d043ea4b15362c9ba889ec13bb7c8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25016 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 diff --git a/test/test_tans_encode_st.c b/test/test_tans_encode_st.c index a7bb884..d4665b4 100644 --- a/test/test_tans_encode_st.c +++ b/test/test_tans_encode_st.c @@ -1,5 +1,6 @@ #include "test.h" +#include "floor_log2.h" #include "tans_buf_bit_writer.h" #include "tans_encode_st.h" @@ -10,19 +11,21 @@ enum test_result test_tans_encode_st_equal_freq(void) 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); @@ -31,7 +34,38 @@ enum test_result test_tans_encode_st_equal_freq(void) 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); } -- 2.34.1