diff mbox

[1/2] Expand bitvec interface

Message ID 1454411973-30799-1-git-send-email-suraev@alumni.ntnu.no
State Changes Requested
Headers show

Commit Message

Suraev Feb. 2, 2016, 11:19 a.m. UTC
From: Max <msuraev@sysmocom.de>

Add bit filling, shifting and other functions necessary for bit
compression implementation. Add corresponding tests.
---
 include/osmocom/core/bitvec.h |   9 +++
 src/bitvec.c                  | 132 ++++++++++++++++++++++++++++++++++++--
 tests/bitvec/bitvec_test.c    | 143 +++++++++++++++++++++++++++++++++++++++++-
 tests/bitvec/bitvec_test.ok   | 119 +++++++++++++++++++++++++++++++++++
 4 files changed, 396 insertions(+), 7 deletions(-)

Comments

Holger Freyther Feb. 4, 2016, 12:39 p.m. UTC | #1
> On 02 Feb 2016, at 12:19, suraev@alumni.ntnu.no wrote:
> 
> 

Dear Max,


> +	memcpy(tmp, bv->data, 2);
> +	return osmo_load16be(tmp) >> (16 - num_bits);

load16be is working byte by byte as well so what do we win by this load?


> +/*! \brief fill num_bits with \fill starting from the current position
> + * returns 0 on success, negative otherwise (out of vector boundary)
> + */
> +int bitvec_fill(struct bitvec *bv, unsigned int num_bits, enum bit_value fill)
> +{
> +	unsigned i, stop = bv->cur_bit + num_bits;
> +	for (i = bv->cur_bit; i < stop; i++)
> +		if (bitvec_set_bit(bv, fill) < 0)
> +			return -EINVAL;
> +
> +	return 0;
> +}
> +
> /*! \brief pad all remaining bits up to num_bits */
> int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit)
> {
> -	unsigned int i;
> -
> -	for (i = bv->cur_bit; i <= up_to_bit; i++)
> -		bitvec_set_bit(bv, L);
> +	int n = up_to_bit - bv->cur_bit + 1;
> +	if (n < 1)
> +		return 0;

so we are going from unsigned to int and then 'n' is "converted" to unsigned int as well. Is this what we want?



> +/*! \brief convert enum to corresponding character */
> +char bit_value_to_char(enum bit_value v)
> +{
> +	switch (v) {
> +	case ZERO: return '0';
> +	case ONE: return '1';
> +	case L: return 'L';
> +	case H: return 'H';
> +	}
> +	/* make compiler happy - "avoid control reaches end of non-void function" warning: */

seeing is believing? Which gcc? I had proposed to use  __builtin_unreachable here. If we know we don't end up there, put this into the "branch" and the warning is gone. Or abort() or __builtin_trap.




> +	return '?';
> +}
> +
> +/*! \brief prints bit vector to provided string
> + * It's caller's responcibility to ensure that we won't shoot him in the foot.

typo, how long is "str"? So either pass a size or write it in the comment of how long it needs to be depending on cur_bit? And what does the _r stand for? Is it similiar to the libc _r functions where an external buffer/pointer is provided?


> +/* we assume that x have at least 1 non-b bit */
> +static inline unsigned _leading_bits(uint8_t x, bool b)

_ and __ are reserved for the system, let us not use it. By having this method as static we already don't pollute the global namespace.


> +/*! \brief Return number (bits) of uninterrupted run of \b in \bv starting from the MSB */

Are you sure that \b and \bv refer to the params? not like \param b, \param bv? Did you look at the documentation generated by doxygen?


> -		fprintf(stderr, "out: %s\n", osmo_hexdump(out, sizeof(out)));
> +		printf("out: %s\n", osmo_hexdump(out, sizeof(out)));

why? more output to be tracked? we could not ignore stderr if we want to?



> 
> 		OSMO_ASSERT(out[0] == 0xff);
> 		OSMO_ASSERT(out[in_size+1] == 0xff);
> @@ -72,11 +145,77 @@ static void test_unhex(const char *hex)
> 
> int main(int argc, char **argv)
> {
> +	srand(time(NULL));

why?
Suraev Feb. 4, 2016, 1:17 p.m. UTC | #2
04.02.2016 13:39, Holger Freyther пишет:

>> +	memcpy(tmp, bv->data, 2);
>> +	return osmo_load16be(tmp) >> (16 - num_bits);
> 
> load16be is working byte by byte as well so what do we win by this load?
> 

I don't really get this - win compared to what? This is new function, not replacement
for some old code.

>> +/*! \brief fill num_bits with \fill starting from the current position
>> + * returns 0 on success, negative otherwise (out of vector boundary)
>> + */
>> +int bitvec_fill(struct bitvec *bv, unsigned int num_bits, enum bit_value fill)
>> +{
>> +	unsigned i, stop = bv->cur_bit + num_bits;
>> +	for (i = bv->cur_bit; i < stop; i++)
>> +		if (bitvec_set_bit(bv, fill) < 0)
>> +			return -EINVAL;
>> +
>> +	return 0;
>> +}
>> +
>> /*! \brief pad all remaining bits up to num_bits */
>> int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit)
>> {
>> -	unsigned int i;
>> -
>> -	for (i = bv->cur_bit; i <= up_to_bit; i++)
>> -		bitvec_set_bit(bv, L);
>> +	int n = up_to_bit - bv->cur_bit + 1;
>> +	if (n < 1)
>> +		return 0;
> 
> so we are going from unsigned to int and then 'n' is "converted" to unsigned int as well. Is this what we want?
> 

Yes. By the time we use n as unsigned we've explicitly checked already that it's
positive. On the other hand the diff between 2 unsigned ints can be signed.

> 
>> +/*! \brief convert enum to corresponding character */
>> +char bit_value_to_char(enum bit_value v)
>> +{
>> +	switch (v) {
>> +	case ZERO: return '0';
>> +	case ONE: return '1';
>> +	case L: return 'L';
>> +	case H: return 'H';
>> +	}
>> +	/* make compiler happy - "avoid control reaches end of non-void function" warning: */
> 
> seeing is believing? Which gcc? I had proposed to use  __builtin_unreachable here. If we know we don't end up there, put this into the "branch" and the warning is gone. Or abort() or __builtin_trap.
> 

I think __builtin_unreachable is deprecated but abort() in default: branch will do
the trick.

> 
> 
> 
>> +	return '?';
>> +}
>> +
>> +/*! \brief prints bit vector to provided string
>> + * It's caller's responcibility to ensure that we won't shoot him in the foot.
> 
> typo, how long is "str"? So either pass a size or write it in the comment of how long it needs to be depending on cur_bit? And what does the _r stand for? Is it similiar to the libc _r functions where an external buffer/pointer is provided?
> 

The name was suggested by Harald in earlier review. The string should be at least
cur_bit+1 bytes long.

> 
>> +/* we assume that x have at least 1 non-b bit */
>> +static inline unsigned _leading_bits(uint8_t x, bool b)
> 
> _ and __ are reserved for the system, let us not use it. By having this method as static we already don't pollute the global namespace.
> 

So how shall it be called to make it clear that this is internal to implementation/file?

> 
>> +/*! \brief Return number (bits) of uninterrupted run of \b in \bv starting from the MSB */
> 
> Are you sure that \b and \bv refer to the params? not like \param b, \param bv? Did you look at the documentation generated by doxygen?

Indeed, it should be \param, or better yet - full comment instead of brief one.

> 
> 
>> -		fprintf(stderr, "out: %s\n", osmo_hexdump(out, sizeof(out)));
>> +		printf("out: %s\n", osmo_hexdump(out, sizeof(out)));
> 
> why? more output to be tracked? we could not ignore stderr if we want to?
> 

We could but since it's tests I'd rather have it under VCS in bitvec_test.ok
explicitly. I think we only should ignore volatile things.

> 
> 
>>
>> 		OSMO_ASSERT(out[0] == 0xff);
>> 		OSMO_ASSERT(out[in_size+1] == 0xff);
>> @@ -72,11 +145,77 @@ static void test_unhex(const char *hex)
>>
>> int main(int argc, char **argv)
>> {
>> +	srand(time(NULL));
> 
> why?
>

Leftover from the time I was thinking of adding tests with random values. Can be
safely removed.

cheers,
Max.
diff mbox

Patch

diff --git a/include/osmocom/core/bitvec.h b/include/osmocom/core/bitvec.h
index a7e6fc4..5314cf2 100644
--- a/include/osmocom/core/bitvec.h
+++ b/include/osmocom/core/bitvec.h
@@ -4,6 +4,7 @@ 
 
 /* (C) 2009 by Harald Welte <laforge@gnumonks.org>
  * (C) 2012 Ivan Klyuchnikov
+ * (C) 2015 Sysmocom s.f.m.c. GmbH
  *
  * All Rights Reserved
  *
@@ -41,6 +42,7 @@ 
 
 #include <stdint.h>
 #include <talloc.h>
+#include <stdbool.h>
 
 /*! \brief A single GSM bit
  *
@@ -82,5 +84,12 @@  unsigned int bitvec_pack(const struct bitvec *bv, uint8_t *buffer);
 unsigned int bitvec_unpack(struct bitvec *bv, const uint8_t *buffer);
 uint64_t bitvec_read_field(struct bitvec *bv, unsigned int *read_index, unsigned int len);
 int bitvec_write_field(struct bitvec *bv, unsigned int *write_index, uint64_t val, unsigned int len);
+int bitvec_fill(struct bitvec *bv, unsigned int num_bits, enum bit_value fill);
+char bit_value_to_char(enum bit_value v);
+void bitvec_to_string_r(const struct bitvec *bv, char *str);
+void bitvec_zero(struct bitvec *bv);
+unsigned bitvec_rl(const struct bitvec *bv, bool b);
+void bitvec_shiftl(struct bitvec *bv, unsigned int n);
+int16_t bitvec_get_int16_msb(const struct bitvec *bv, unsigned int num_bits);
 
 /*! @} */
diff --git a/src/bitvec.c b/src/bitvec.c
index b5d2c24..fc016a6 100644
--- a/src/bitvec.c
+++ b/src/bitvec.c
@@ -34,7 +34,9 @@ 
 #include <stdint.h>
 #include <string.h>
 #include <stdio.h>
+#include <stdbool.h>
 
+#include <osmocom/core/bits.h>
 #include <osmocom/core/bitvec.h>
 
 #define BITNUM_FROM_COMP(byte, bit)	((byte*8)+bit)
@@ -224,6 +226,20 @@  int bitvec_set_uint(struct bitvec *bv, unsigned int ui, unsigned int num_bits)
 	return 0;
 }
 
+/*! \brief get multiple bits (num_bits) from beginning of vector (MSB side) */
+int16_t bitvec_get_int16_msb(const struct bitvec *bv, unsigned int num_bits)
+{
+	uint8_t tmp[2];
+	if (num_bits > 15 || bv->cur_bit < num_bits)
+		return -EINVAL;
+
+	if (num_bits < 9)
+		return bv->data[0] >> (8 - num_bits);
+
+	memcpy(tmp, bv->data, 2);
+	return osmo_load16be(tmp) >> (16 - num_bits);
+}
+
 /*! \brief get multiple bits (based on numeric value) from current pos */
 int bitvec_get_uint(struct bitvec *bv, unsigned int num_bits)
 {
@@ -242,15 +258,27 @@  int bitvec_get_uint(struct bitvec *bv, unsigned int num_bits)
 	return ui;
 }
 
+/*! \brief fill num_bits with \fill starting from the current position
+ * returns 0 on success, negative otherwise (out of vector boundary)
+ */
+int bitvec_fill(struct bitvec *bv, unsigned int num_bits, enum bit_value fill)
+{
+	unsigned i, stop = bv->cur_bit + num_bits;
+	for (i = bv->cur_bit; i < stop; i++)
+		if (bitvec_set_bit(bv, fill) < 0)
+			return -EINVAL;
+
+	return 0;
+}
+
 /*! \brief pad all remaining bits up to num_bits */
 int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit)
 {
-	unsigned int i;
-
-	for (i = bv->cur_bit; i <= up_to_bit; i++)
-		bitvec_set_bit(bv, L);
+	int n = up_to_bit - bv->cur_bit + 1;
+	if (n < 1)
+		return 0;
 
-	return 0;
+	return bitvec_fill(bv, n, L);
 }
 
 /*! \brief find first bit set in bit vector */
@@ -446,4 +474,98 @@  int bitvec_write_field(struct bitvec *bv, unsigned int *write_index, uint64_t va
 	return 0;
 }
 
+/*! \brief convert enum to corresponding character */
+char bit_value_to_char(enum bit_value v)
+{
+	switch (v) {
+	case ZERO: return '0';
+	case ONE: return '1';
+	case L: return 'L';
+	case H: return 'H';
+	}
+	/* make compiler happy - "avoid control reaches end of non-void function" warning: */
+	return '?';
+}
+
+/*! \brief prints bit vector to provided string
+ * It's caller's responcibility to ensure that we won't shoot him in the foot.
+ */
+void bitvec_to_string_r(const struct bitvec *bv, char *str)
+{
+	unsigned i, pos = 0;
+	char *cur = str;
+	for (i = 0; i < bv->cur_bit; i++) {
+		if (0 == i % 8)
+			*cur++ = ' ';
+		*cur++ = bit_value_to_char(bitvec_get_bit_pos(bv, i));
+		pos++;
+	}
+	*cur = 0;
+}
+
+/* we assume that x have at least 1 non-b bit */
+static inline unsigned _leading_bits(uint8_t x, bool b)
+{
+	if (b) {
+		if (x < 0x80) return 0;
+		if (x < 0xC0) return 1;
+		if (x < 0xE0) return 2;
+		if (x < 0xF0) return 3;
+		if (x < 0xF8) return 4;
+		if (x < 0xFC) return 5;
+		if (x < 0xFE) return 6;
+	} else {
+		if (x > 0x7F) return 0;
+		if (x > 0x3F) return 1;
+		if (x > 0x1F) return 2;
+		if (x > 0xF) return 3;
+		if (x > 7) return 4;
+		if (x > 3) return 5;
+		if (x > 1) return 6;
+	}
+	return 7;
+}
+/*! \brief force bit vector to all 0 and current bit to the beginnig of the vector */
+void bitvec_zero(struct bitvec *bv)
+{
+	bv->cur_bit = 0;
+	memset(bv->data, 0, bv->data_len);
+}
+
+/*! \brief Return number (bits) of uninterrupted run of \b in \bv starting from the MSB */
+unsigned bitvec_rl(const struct bitvec *bv, bool b)
+{
+	unsigned i;
+	for (i = 0; i < (bv->cur_bit % 8 ? bv->cur_bit / 8 + 1 : bv->cur_bit / 8); i++) {
+		if ( (b ? 0xFF : 0) != bv->data[i])
+			return i * 8 + _leading_bits(bv->data[i], b);
+	}
+
+	return bv->cur_bit;
+}
+
+/*! \brief Shifts bitvec to the left, n MSB bits lost */
+void bitvec_shiftl(struct bitvec *bv, unsigned n)
+{
+	if (0 == n)
+		return;
+	if (n >= bv->cur_bit) {
+		bitvec_zero(bv);
+		return;
+	}
+
+	memmove(bv->data, bv->data + n / 8, bv->data_len - n / 8);
+
+	uint8_t tmp[2];
+	unsigned i;
+	for (i = 0; i < bv->data_len - 2; i++) {
+		uint16_t t = osmo_load16be(bv->data + i);
+		osmo_store16be(t << (n % 8), &tmp);
+		bv->data[i] = tmp[0];
+	}
+
+	bv->data[bv->data_len - 1] <<= (n % 8);
+	bv->cur_bit -= n;
+}
+
 /*! @} */
diff --git a/tests/bitvec/bitvec_test.c b/tests/bitvec/bitvec_test.c
index 7d131e0..4fc9db3 100644
--- a/tests/bitvec/bitvec_test.c
+++ b/tests/bitvec/bitvec_test.c
@@ -3,9 +3,82 @@ 
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
+#include <time.h>
+#include <stdbool.h>
+#include <errno.h>
 
 #include <osmocom/core/utils.h>
 #include <osmocom/core/bitvec.h>
+#include <osmocom/core/bits.h>
+
+#define BIN_PATTERN "%d%d%d%d%d%d%d%d"
+#define BIN(byte)  \
+  (byte & 0x80 ? 1 : 0), \
+  (byte & 0x40 ? 1 : 0), \
+  (byte & 0x20 ? 1 : 0), \
+  (byte & 0x10 ? 1 : 0), \
+  (byte & 0x08 ? 1 : 0), \
+  (byte & 0x04 ? 1 : 0), \
+  (byte & 0x02 ? 1 : 0), \
+  (byte & 0x01 ? 1 : 0)
+
+static char lol[1024]; // we pollute this with printed vectors
+static inline void test_rl(const struct bitvec *bv)
+{
+	bitvec_to_string_r(bv, lol);
+	printf("%s [%d] RL0=%d, RL1=%d\n", lol, bv->cur_bit, bitvec_rl(bv, false), bitvec_rl(bv, true));
+}
+
+static inline void test_shift(struct bitvec *bv, unsigned n)
+{
+	bitvec_to_string_r(bv, lol);
+	printf("%s << %d:\n", lol, n);
+	bitvec_shiftl(bv, n);
+	bitvec_to_string_r(bv, lol);
+	printf("%s\n", lol);
+}
+
+static inline void test_get(struct bitvec *bv, unsigned n)
+{
+	bitvec_to_string_r(bv, lol);
+	printf("%s [%d]", lol, bv->cur_bit);
+	int16_t x = bitvec_get_int16_msb(bv, n);
+	uint8_t tmp[2];
+	osmo_store16be(x, &tmp);
+	printf(" -> %d (%u bit) ["BIN_PATTERN" "BIN_PATTERN"]:\n", x, n, BIN(tmp[0]), BIN(tmp[1]));
+	bitvec_to_string_r(bv, lol);
+	printf("%s [%d]\n", lol, bv->cur_bit);
+}
+
+static inline void test_fill(struct bitvec *bv, unsigned n, enum bit_value val)
+{
+	bitvec_to_string_r(bv, lol);
+	unsigned bvlen = bv->cur_bit;
+	int fi =  bitvec_fill(bv, n, val);
+	printf("%c>  FILL %s [%d] -%d-> [%d]:\n", bit_value_to_char(val), lol, bvlen, n, fi);
+	bitvec_to_string_r(bv, lol);
+	printf("         %s [%d]\n\n", lol, bv->cur_bit);
+}
+
+static inline void test_spare(struct bitvec *bv, unsigned n)
+{
+	bitvec_to_string_r(bv, lol);
+	unsigned bvlen = bv->cur_bit;
+	int sp = bitvec_spare_padding(bv, n);
+	printf("%c> SPARE %s [%d] -%d-> [%d]:\n", bit_value_to_char(L), lol, bvlen, n, sp);
+	bitvec_to_string_r(bv, lol);
+	printf("         %s [%d]\n\n", lol, bv->cur_bit);
+}
+
+static inline void test_set(struct bitvec *bv, enum bit_value bit)
+{
+	bitvec_to_string_r(bv, lol);
+	unsigned bvlen = bv->cur_bit;
+	int set = bitvec_set_bit(bv, bit);
+	printf("%c>   SET %s [%d] ++> [%d]:\n", bit_value_to_char(bit), lol, bvlen, set);
+	bitvec_to_string_r(bv, lol);
+	printf("         %s [%d]\n\n", lol, bv->cur_bit);
+}
 
 static void test_byte_ops()
 {
@@ -33,7 +106,7 @@  static void test_byte_ops()
 		rc = bitvec_set_uint(&bv, 0x7e, 8);
 		OSMO_ASSERT(rc >= 0);
 
-		fprintf(stderr, "bitvec: %s\n", osmo_hexdump(bv.data, bv.data_len));
+		printf("bitvec: %s\n", osmo_hexdump(bv.data, bv.data_len));
 
 		/* Read from bitvec */
 		memset(out, 0xff, sizeof(out));
@@ -45,7 +118,7 @@  static void test_byte_ops()
 		rc = bitvec_get_uint(&bv, 8);
 		OSMO_ASSERT(rc == 0x7e);
 
-		fprintf(stderr, "out: %s\n", osmo_hexdump(out, sizeof(out)));
+		printf("out: %s\n", osmo_hexdump(out, sizeof(out)));
 
 		OSMO_ASSERT(out[0] == 0xff);
 		OSMO_ASSERT(out[in_size+1] == 0xff);
@@ -72,11 +145,77 @@  static void test_unhex(const char *hex)
 
 int main(int argc, char **argv)
 {
+	srand(time(NULL));
+
+	struct bitvec bv;
+	uint8_t i = 8, test[i];
+
+	memset(test, 0, i);
+	bv.data_len = i;
+	bv.data = test;
+	bv.cur_bit = 0;
+
+	printf("test shifting...\n");
+
+	bitvec_set_uint(&bv, 0x0E, 7);
+	test_shift(&bv, 3);
+	test_shift(&bv, 17);
+	bitvec_set_uint(&bv, 0, 32);
+	bitvec_set_uint(&bv, 0x0A, 7);
+	test_shift(&bv, 24);
+
+	printf("checking RL functions...\n");
+
+	bitvec_zero(&bv);
+	test_rl(&bv);
+	bitvec_set_uint(&bv, 0x000F, 32);
+	test_rl(&bv);
+	bitvec_shiftl(&bv, 18);
+	test_rl(&bv);
+	bitvec_set_uint(&bv, 0x0F, 8);
+	test_rl(&bv);
+	bitvec_zero(&bv);
+	bitvec_set_uint(&bv, 0xFF, 8);
+	test_rl(&bv);
+	bitvec_set_uint(&bv, 0xFE, 7);
+	test_rl(&bv);
+	bitvec_set_uint(&bv, 0, 17);
+	test_rl(&bv);
+	bitvec_shiftl(&bv, 18);
+	test_rl(&bv);
+
+	printf("probing bit access...\n");
+
+	bitvec_zero(&bv);
+	bitvec_set_uint(&bv, 0x3747817, 32);
+	bitvec_shiftl(&bv, 10);
+
+	test_get(&bv, 2);
+	test_get(&bv, 7);
+	test_get(&bv, 9);
+	test_get(&bv, 13);
+	test_get(&bv, 16);
+	test_get(&bv, 42);
+
+	printf("feeling bit fills...\n");
+
+	test_set(&bv, ONE);
+	test_fill(&bv, 3, ZERO);
+	test_spare(&bv, 38);
+	test_spare(&bv, 43);
+	test_spare(&bv, 1);
+	test_spare(&bv, 7);
+	test_fill(&bv, 5, ONE);
+	test_fill(&bv, 3, L);
+
+	printf("byte me...\n");
+
 	test_byte_ops();
 	test_unhex("48282407a6a074227201000b2b2b2b2b2b2b2b2b2b2b2b");
 	test_unhex("47240c00400000000000000079eb2ac9402b2b2b2b2b2b");
 	test_unhex("47283c367513ba333004242b2b2b2b2b2b2b2b2b2b2b2b");
 	test_unhex("DEADFACE000000000000000000000000000000BEEFFEED");
 	test_unhex("FFFFFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
+
 	return 0;
 }
diff --git a/tests/bitvec/bitvec_test.ok b/tests/bitvec/bitvec_test.ok
index 83328b2..1c993d3 100644
--- a/tests/bitvec/bitvec_test.ok
+++ b/tests/bitvec/bitvec_test.ok
@@ -1,4 +1,123 @@ 
+test shifting...
+ 0001110 << 3:
+ 1110
+ 1110 << 17:
+
+ 00000000 00000000 00000000 00000000 0001010 << 24:
+ 00000000 0001010
+checking RL functions...
+ [0] RL0=0, RL1=0
+ 00000000 00000000 00000000 00001111 [32] RL0=28, RL1=0
+ 00000000 001111 [14] RL0=10, RL1=0
+ 00000000 00111100 001111 [22] RL0=10, RL1=0
+ 11111111 [8] RL0=0, RL1=8
+ 11111111 1111110 [15] RL0=0, RL1=14
+ 11111111 11111100 00000000 00000000 [32] RL0=0, RL1=14
+ 00000000 000000 [14] RL0=14, RL1=0
+probing bit access...
+ 11010001 11100000 010111 [22] -> 3 (2 bit) [00000000 00000011]:
+ 11010001 11100000 010111 [22]
+ 11010001 11100000 010111 [22] -> 104 (7 bit) [00000000 01101000]:
+ 11010001 11100000 010111 [22]
+ 11010001 11100000 010111 [22] -> 419 (9 bit) [00000001 10100011]:
+ 11010001 11100000 010111 [22]
+ 11010001 11100000 010111 [22] -> 6716 (13 bit) [00011010 00111100]:
+ 11010001 11100000 010111 [22]
+ 11010001 11100000 010111 [22] -> -22 (16 bit) [11111111 11101010]:
+ 11010001 11100000 010111 [22]
+ 11010001 11100000 010111 [22] -> -22 (42 bit) [11111111 11101010]:
+ 11010001 11100000 010111 [22]
+feeling bit fills...
+1>   SET  11010001 11100000 010111 [22] ++> [0]:
+          11010001 11100000 0101111 [23]
+
+0>  FILL  11010001 11100000 0101111 [23] -3-> [0]:
+          11010001 11100000 01011110 00 [26]
+
+L> SPARE  11010001 11100000 01011110 00 [26] -38-> [0]:
+          11010001 11100000 01011110 00101011 0010101 [39]
+
+L> SPARE  11010001 11100000 01011110 00101011 0010101 [39] -43-> [0]:
+          11010001 11100000 01011110 00101011 00101011 0010 [44]
+
+L> SPARE  11010001 11100000 01011110 00101011 00101011 0010 [44] -1-> [0]:
+          11010001 11100000 01011110 00101011 00101011 0010 [44]
+
+L> SPARE  11010001 11100000 01011110 00101011 00101011 0010 [44] -7-> [0]:
+          11010001 11100000 01011110 00101011 00101011 0010 [44]
+
+1>  FILL  11010001 11100000 01011110 00101011 00101011 0010 [44] -5-> [0]:
+          11010001 11100000 01011110 00101011 00101011 00101111 1 [49]
+
+L>  FILL  11010001 11100000 01011110 00101011 00101011 00101111 1 [49] -3-> [0]:
+          11010001 11100000 01011110 00101011 00101011 00101111 1010 [52]
+
+byte me...
 === start test_byte_ops ===
+bitvec: 7e 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 3f 20 a1 21 a2 22 a3 23 a4 24 a5 25 a6 26 a7 27 a8 28 a9 29 aa 2a ab 2b ac 2c ad 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 1f 90 50 90 d1 11 51 91 d2 12 52 92 d3 13 53 93 d4 14 54 94 d5 15 55 95 d6 16 56 9f 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 0f c8 28 48 68 88 a8 c8 e9 09 29 49 69 89 a9 c9 ea 0a 2a 4a 6a 8a aa ca eb 0b 2b 4f c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 07 e4 14 24 34 44 54 64 74 84 94 a4 b4 c4 d4 e4 f5 05 15 25 35 45 55 65 75 85 95 a7 e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 03 f2 0a 12 1a 22 2a 32 3a 42 4a 52 5a 62 6a 72 7a 82 8a 92 9a a2 aa b2 ba c2 ca d3 f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 01 f9 05 09 0d 11 15 19 1d 21 25 29 2d 31 35 39 3d 41 45 49 4d 51 55 59 5d 61 65 69 f8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 fc 82 84 86 88 8a 8c 8e 90 92 94 96 98 9a 9c 9e a0 a2 a4 a6 a8 aa ac ae b0 b2 b4 fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 7e 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 3f 20 a1 21 a2 22 a3 23 a4 24 a5 25 a6 26 a7 27 a8 28 a9 29 aa 2a ab 2b ac 2c ad 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 1f 90 50 90 d1 11 51 91 d2 12 52 92 d3 13 53 93 d4 14 54 94 d5 15 55 95 d6 16 56 9f 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 0f c8 28 48 68 88 a8 c8 e9 09 29 49 69 89 a9 c9 ea 0a 2a 4a 6a 8a aa ca eb 0b 2b 4f c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 07 e4 14 24 34 44 54 64 74 84 94 a4 b4 c4 d4 e4 f5 05 15 25 35 45 55 65 75 85 95 a7 e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 03 f2 0a 12 1a 22 2a 32 3a 42 4a 52 5a 62 6a 72 7a 82 8a 92 9a a2 aa b2 ba c2 ca d3 f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 01 f9 05 09 0d 11 15 19 1d 21 25 29 2d 31 35 39 3d 41 45 49 4d 51 55 59 5d 61 65 69 f8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 fc 82 84 86 88 8a 8c 8e 90 92 94 96 98 9a 9c 9e a0 a2 a4 a6 a8 aa ac ae b0 b2 b4 fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 7e 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 3f 20 a1 21 a2 22 a3 23 a4 24 a5 25 a6 26 a7 27 a8 28 a9 29 aa 2a ab 2b ac 2c ad 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 1f 90 50 90 d1 11 51 91 d2 12 52 92 d3 13 53 93 d4 14 54 94 d5 15 55 95 d6 16 56 9f 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 0f c8 28 48 68 88 a8 c8 e9 09 29 49 69 89 a9 c9 ea 0a 2a 4a 6a 8a aa ca eb 0b 2b 4f c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 07 e4 14 24 34 44 54 64 74 84 94 a4 b4 c4 d4 e4 f5 05 15 25 35 45 55 65 75 85 95 a7 e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 03 f2 0a 12 1a 22 2a 32 3a 42 4a 52 5a 62 6a 72 7a 82 8a 92 9a a2 aa b2 ba c2 ca d3 f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 01 f9 05 09 0d 11 15 19 1d 21 25 29 2d 31 35 39 3d 41 45 49 4d 51 55 59 5d 61 65 69 f8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 00 fc 82 84 86 88 8a 8c 8e 90 92 94 96 98 9a 9c 9e a0 a2 a4 a6 a8 aa ac ae b0 b2 b4 fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 00 7e 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 00 3f 20 a1 21 a2 22 a3 23 a4 24 a5 25 a6 26 a7 27 a8 28 a9 29 aa 2a ab 2b ac 2c ad 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 00 1f 90 50 90 d1 11 51 91 d2 12 52 92 d3 13 53 93 d4 14 54 94 d5 15 55 95 d6 16 56 9f 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 00 0f c8 28 48 68 88 a8 c8 e9 09 29 49 69 89 a9 c9 ea 0a 2a 4a 6a 8a aa ca eb 0b 2b 4f c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 00 07 e4 14 24 34 44 54 64 74 84 94 a4 b4 c4 d4 e4 f5 05 15 25 35 45 55 65 75 85 95 a7 e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 00 03 f2 0a 12 1a 22 2a 32 3a 42 4a 52 5a 62 6a 72 7a 82 8a 92 9a a2 aa b2 ba c2 ca d3 f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 00 01 f9 05 09 0d 11 15 19 1d 21 25 29 2d 31 35 39 3d 41 45 49 4d 51 55 59 5d 61 65 69 f8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
+bitvec: 00 00 00 00 fc 82 84 86 88 8a 8c 8e 90 92 94 96 98 9a 9c 9e a0 a2 a4 a6 a8 aa ac ae b0 b2 b4 fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+out: ff 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a ff 
 === end test_byte_ops ===
 1 -=> cur_bit=184
 48282407a6a074227201000b2b2b2b2b2b2b2b2b2b2b2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000