From 9d0f0b2c714819d93eb29f0f00fd5aa600da880f Mon Sep 17 00:00:00 2001 From: Syndamia Date: Wed, 27 May 2026 15:07:20 +0300 Subject: feat: Implement B_newstr --- BigInt.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- example.c | 4 ++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/BigInt.c b/BigInt.c index d5b1d20..e0014cc 100644 --- a/BigInt.c +++ b/BigInt.c @@ -2,6 +2,7 @@ #include "MemoryManager.h" #include "Types.h" #include +#include #include typedef uint_fast32_t UWord; @@ -72,11 +73,54 @@ B_new(MemoryManager *mm, int value) { BigInt B_newstr(MemoryManager *mm, const char* str) { - return NULL; + if (NULL == str) + return NULL; + + usize len = strlen(str); + + UWord *num = B_newbytes(mm, len / 2); + if (NULL == num) + return NULL; + + UWord *bcd = B_newbytes(mm, len / 2); + if (NULL == bcd) { + mm->free(*mm, (void**)&num); + return NULL; + } + + struct BigIntMeta *numm = B_metadata(num); + struct BigIntMeta *bcdm = B_metadata(bcd); + + // char string to BCD + for (const char *s = str; *s != '\0'; ++s) { + B_lshift((BigInt*)&bcd, 4); + bcd[0] |= *s - '0'; + } + + // Double-dable bcd to BigInt + for (usize i = len * 4; i > 0; --i) { + B_rshift((BigInt*)&num, 1); + num[numm->words - 1] |= (UWord)(bcd[0] & 1) << (UWORD_BIT - 1); + B_rshift((BigInt*)&bcd, 1); + + for (usize w = 0; w < bcdm->words; ++w) { + for (UWord mask = 0b1111, eight = 8, three = 3; mask > 0; mask <<= 4, eight <<= 4, three <<= 4) { + if ((bcd[w] & mask) >= eight) + bcd[w] -= three; + } + } + } + B_rshift((BigInt*)&num, UWORD_BIT * numm->words - len * 4); + + mm->free(*mm, (void**)&bcd); + + return num; } BigInt B_newbytes(MemoryManager *mm, usize bytes) { + if (0 == bytes) + return B_start(mm, 1); return B_start(mm, 1 + (bytes - 1) / sizeof(UWord)); } @@ -214,7 +258,7 @@ B_rshift(BigInt *intx, usize shift) { struct BigIntMeta *bim = B_metadata(*intx); UWord *x = *intx; - usize word_moves = shift / (sizeof(UWord) * CHAR_BIT); + usize word_moves = shift / UWORD_BIT; if (word_moves) { usize w = 0; for (; w < bim->words - word_moves; ++w) @@ -357,7 +401,7 @@ B_tostr(MemoryManager *mm, BigInt intx) { } memset(bcd, 0, sizeof(u8) * bcd_bytes); - UWord mask = (UWord)1 << (sizeof(UWord) * 8 - 1); + UWord mask = (UWord)1 << (UWORD_BIT - 1); // Double-dable, binary to binary-coded decimal for (usize w = bim->words - 1; w < bim->words; --w) { diff --git a/example.c b/example.c index 52d402e..420264a 100644 --- a/example.c +++ b/example.c @@ -68,6 +68,10 @@ main() { astr = B_tostr(&g, a); printf("a >> 30 = %s\n", astr); + BigInt c = B_newstr(&g, "12345678901234567890123"); + astr = B_tostr(&g, c); + printf("c = %s\n", astr); + PRINT_NOTOK(g.destroy(&g)); PRINT_NOTOK(t.destroy(&t)); PRINT_NOTOK(T.destroy(&T)); -- cgit v1.2.3