From 7e0b603b78adf4c1704b757da05d085e03afe5f6 Mon Sep 17 00:00:00 2001 From: Syndamia Date: Sat, 23 May 2026 09:56:17 +0300 Subject: feat(BigInt): Implement bit shifts and add math in example --- BigInt.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BigInt.h | 3 +++ example.c | 26 +++++++++++++++++++ 3 files changed, 118 insertions(+) diff --git a/BigInt.c b/BigInt.c index b9239d7..4ffee57 100644 --- a/BigInt.c +++ b/BigInt.c @@ -73,6 +73,11 @@ B_newstr(MemoryManager *mm, const char* str) { return NULL; } +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) @@ -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 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)); -- cgit v1.2.3