aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/util/bits.c18
-rw-r--r--src/util/bits.h2
-rw-r--r--test/src/util/test_bits.c11
3 files changed, 31 insertions, 0 deletions
diff --git a/src/util/bits.c b/src/util/bits.c
index e5f28c1..6311ba8 100644
--- a/src/util/bits.c
+++ b/src/util/bits.c
@@ -49,6 +49,24 @@ bits_t *bits_from_i(GEN i) {
return result;
}
+bits_t *bits_from_i_len(GEN i, size_t bit_len) {
+ pari_sp ltop = avma;
+ GEN bitvec = binary_zv(i);
+ size_t i_len = (size_t)glength(bitvec);
+ bits_t *result = bits_new(bit_len);
+ size_t offset = 0;
+ if (i_len < bit_len) {
+ offset = bit_len - i_len;
+ }
+ for (size_t j = 0; j < bit_len; ++j) {
+ if (j < i_len && gel(bitvec, j + 1) == (GEN)1) {
+ result->bits[(j + offset) / 8] |= 1 << (7 - ((j + offset) % 8));
+ }
+ }
+ avma = ltop;
+ return result;
+}
+
bits_t *bits_from_hex(const char *hex_str) {
size_t nibble_len = strlen(hex_str);
bits_t *result = bits_new(nibble_len * 4);
diff --git a/src/util/bits.h b/src/util/bits.h
index 2766cc3..9b37539 100644
--- a/src/util/bits.h
+++ b/src/util/bits.h
@@ -35,6 +35,8 @@ void bits_free(bits_t **bits);
bits_t *bits_from_i(GEN i);
+bits_t *bits_from_i_len(GEN i, size_t bitlen);
+
bits_t *bits_from_hex(const char *hex_str);
bits_t *bits_from_bin(const char *bin_str);
diff --git a/test/src/util/test_bits.c b/test/src/util/test_bits.c
index 70060c9..a7b38e3 100644
--- a/test/src/util/test_bits.c
+++ b/test/src/util/test_bits.c
@@ -48,6 +48,17 @@ Test(bits, test_bits_from_i) {
bits_free(&bits);
}
+Test(bits, test_bits_from_i_len) {
+ GEN i = int2n(5);
+
+ bits_t *bits = bits_from_i_len(i, 7);
+ cr_assert_not_null(bits, );
+ cr_assert_eq(bits->bitlen, 7, );
+ cr_assert_eq(bits->allocated, 1, );
+ cr_assert_eq(bits->bits[0], 0b01000000, );
+ bits_free(&bits);
+}
+
Test(bits, test_bits_from_hex) {
char *hex = "0ab";