From a1dd57402151e289a6297b42f5a3bafe4769730f Mon Sep 17 00:00:00 2001 From: ocsmit Date: Thu, 20 Jul 2023 09:41:36 -0400 Subject: [PATCH] Add encoding routines --- src/encoding.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/encoding.h | 19 ++++++++++++++++ tests/tests.c | 12 ++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/encoding.c create mode 100644 src/encoding.h diff --git a/src/encoding.c b/src/encoding.c new file mode 100644 index 0000000..2a1fe56 --- /dev/null +++ b/src/encoding.c @@ -0,0 +1,60 @@ +/** + * @file + * @brief Routines for encoding and decoding integers + */ + +#include "encoding.h" + +#include +#include + + +uint32_t count_trailing_zeros(unsigned int v) +{ + // modified from: + // http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup + static const uint32_t Mod37BitPosition[] = { + 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, + 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, + 20, 8, 19, 18 + }; + + // map a bit value mod 37 to its position + return Mod37BitPosition[(-v & v) % 37]; +} + + +unsigned int unary_encode(uint32_t k) +{ + // code 1 . 0 k times (e.g. 3 := 1 . 000 + return (1 << k); + +} + +unsigned int gamma_encode(uint32_t k) +{ + uint32_t length, offset; + + // floor(log_2(k)) + length = (uint32_t) log2(k); + offset = k - (1 << length); + + // Unary coded offset . length + // e.g. 13 (l = 3, o = 5) := 101.1000 + return (offset << (length+1) | ((1 << length))); +} + +unsigned int gamma_decode(unsigned int k) +{ + uint32_t l = 0; + uint32_t o = 0; + + l = count_trailing_zeros(k); + k >>= l; + + // Mask for l bits + o = (1 << l) - 1 & (k >> 1); + return (1 << l) + o; +} + + diff --git a/src/encoding.h b/src/encoding.h new file mode 100644 index 0000000..fecda75 --- /dev/null +++ b/src/encoding.h @@ -0,0 +1,19 @@ +#ifndef ENCODING_H_ +#define ENCODING_H_ + +#include +#include + + + + +uint32_t count_trailing_zeros(unsigned int v); + +unsigned int unary_encode(uint32_t k); + +unsigned int gamma_encode(uint32_t k); + +unsigned int gamma_decode(unsigned int k); + +#endif // !ENCODING_H_ + diff --git a/tests/tests.c b/tests/tests.c index a4ed48a..e395807 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -1,9 +1,12 @@ #include "tests.h" #include "assert.h" +#include #include #include "../src/bitarr.h" #include "../src/bitops.h" #include "../src/bitarr_io.h" +#include "../src/encoding.h" + @@ -132,6 +135,15 @@ TEST("Read from disk") BitArray_free(bit_arr); +TEST("Gamma encoding") +{ + uint32_t og_int = 13; + unsigned int gc = gamma_encode(og_int); + gc = gamma_decode(gc); + assert(og_int == gc); + printf("✔ Gamma coding\n"); +} + -- 2.45.2