aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BigInt.c89
-rw-r--r--BigInt.h3
-rw-r--r--example.c26
3 files changed, 118 insertions, 0 deletions
diff --git a/BigInt.c b/BigInt.c
index b9239d7..4ffee57 100644
--- a/BigInt.c
+++ b/BigInt.c
@@ -74,6 +74,11 @@ B_newstr(MemoryManager *mm, const char* str) {
}
BigInt
+B_newbytes(MemoryManager *mm, usize bytes) {
+ return B_start(mm, 1 + (bytes - 1) / sizeof(UWord));
+}
+
+BigInt
B_dup(MemoryManager *mm, BigInt bigint) {
if (NULL == bigint)
return NULL;
@@ -196,6 +201,90 @@ B_sub(BigInt *inta, BigInt intb) {
return R_Ok;
}
+Result
+B_rshift(BigInt *intx, usize shift) {
+ if (NULL == intx || NULL == *intx)
+ return R_NullArgument;
+
+ if (shift == 0)
+ return R_Ok;
+
+ struct BigIntMeta *bim = B_metadata(*intx);
+ UWord *x = *intx;
+
+ usize word_moves = shift / (sizeof(UWord) * 8);
+ if (word_moves) {
+ usize w = 0;
+ for (; w < bim->words - word_moves; ++w)
+ x[w] = x[w + word_moves];
+ for (; w < bim->words; ++w)
+ x[w] = 0;
+ }
+
+ usize bit_moves = shift % (sizeof(UWord) * 8);
+ if (bit_moves == 1) {
+ x[0] >>= 1;
+ for (usize w = 1; w < bim->words; ++w) {
+ x[w - 1] |= (x[w] & 1) << (sizeof(UWord) * 8 - 1);
+ x[w] >>= 1;
+ }
+ }
+ else if (bit_moves > 1) {
+ UWord mask = ((UWord)1 << bit_moves) - 1;
+
+ x[0] >>= bit_moves;
+ for (usize w = 1; w < bim->words; ++w) {
+ x[w - 1] |= (x[w] & mask) << (sizeof(UWord) * 8 - bit_moves);
+ x[w] >>= bit_moves;
+ }
+ }
+
+ return R_Ok;
+}
+
+Result
+B_lshift(BigInt *intx, usize shift) {
+ if (NULL == intx || NULL == *intx)
+ return R_NullArgument;
+
+ if (shift == 0)
+ return R_Ok;
+
+ struct BigIntMeta *bim = B_metadata(*intx);
+ UWord *x = *intx;
+
+ usize word_moves = shift / (sizeof(UWord) * 8);
+ if (word_moves) {
+ usize w = bim->words - 1;
+ for (; w >= word_moves; --w)
+ x[w] = x[w - word_moves];
+ for (; w < bim->words; --w)
+ x[w] = 0;
+ }
+
+ usize bit_moves = shift % (sizeof(UWord) * 8);
+ if (bit_moves == 1) {
+ UWord mask = (UWord)1 << (sizeof(UWord) * 8 - 1);
+
+ x[bim->words - 1] <<= 1;
+ for (usize w = bim->words - 2; w < bim->words; --w) {
+ x[w + 1] |= (x[w] & mask) >> (sizeof(UWord) * 8 - 1);
+ x[w] <<= 1;
+ }
+ }
+ else if (bit_moves > 1) {
+ UWord mask = (((UWord)1 << bit_moves) - 1) << (sizeof(UWord) * 8 - bit_moves);
+
+ x[bim->words - 1] <<= bit_moves;
+ for (usize w = bim->words - 2; w < bim->words; --w) {
+ x[w + 1] |= (x[w] & mask) >> (sizeof(UWord) * 8 - bit_moves);
+ x[w] <<= bit_moves;
+ }
+ }
+
+ return R_Ok;
+}
+
/* Get */
usize
diff --git a/BigInt.h b/BigInt.h
index 2324143..913e249 100644
--- a/BigInt.h
+++ b/BigInt.h
@@ -9,6 +9,7 @@ typedef void* BigInt;
BigInt B_new(MemoryManager *mm, int value);
BigInt B_newstr(MemoryManager *mm, const char* str);
+BigInt B_newbytes(MemoryManager *mm, usize bytes);
BigInt B_dup(MemoryManager *mm, BigInt bigint);
BigInt B_newsum(MemoryManager *mm, BigInt a, BigInt b);
@@ -22,6 +23,8 @@ Result B_free(BigInt *bigint);
Result B_sum(BigInt *a, BigInt b);
Result B_sub(BigInt *a, BigInt b);
+Result B_rshift(BigInt *x, usize shift);
+Result B_lshift(BigInt *x, usize shift);
/* Get */
diff --git a/example.c b/example.c
index 6dc3525..52d402e 100644
--- a/example.c
+++ b/example.c
@@ -3,6 +3,7 @@
#include "Vector.h"
#include "String.h"
#include "BumpAlloc.h"
+#include "BigInt.h"
#include <stdio.h>
int
@@ -42,6 +43,31 @@ main() {
PRINT_NOTOK(H_freevals(&tet));
PRINT_NOTOK(H_free(&tet));
+ BigInt a = B_new(&g, -1),
+ b = B_new(&g, 1);
+
+ {
+ uint_fast32_t *aa = a;
+ aa[0] = -1;
+ }
+
+ B_sum(&a, b);
+ char *astr = B_tostr(&g, a);
+ printf("a + b = %s\n", astr);
+
+ B_sub(&a, b);
+ B_sub(&a, b);
+ astr = B_tostr(&g, a);
+ printf("a - b = %s\n", astr);
+
+ B_lshift(&a, 30);
+ astr = B_tostr(&g, a);
+ printf("a << 30 = %s\n", astr);
+
+ B_rshift(&a, 30);
+ astr = B_tostr(&g, a);
+ printf("a >> 30 = %s\n", astr);
+
PRINT_NOTOK(g.destroy(&g));
PRINT_NOTOK(t.destroy(&t));
PRINT_NOTOK(T.destroy(&T));