diff options
| author | Syndamia <kamen@syndamia.com> | 2026-05-27 15:07:20 +0300 |
|---|---|---|
| committer | Syndamia <kamen@syndamia.com> | 2026-07-12 09:14:06 +0300 |
| commit | 9d0f0b2c714819d93eb29f0f00fd5aa600da880f (patch) | |
| tree | 6b2c28b21253ea65bb9675acb85e2dbb204d7535 | |
| parent | 2d5995f3a8040fde50300f3bf2515dbf2dbede36 (diff) | |
| download | foollib-9d0f0b2c714819d93eb29f0f00fd5aa600da880f.tar foollib-9d0f0b2c714819d93eb29f0f00fd5aa600da880f.tar.gz foollib-9d0f0b2c714819d93eb29f0f00fd5aa600da880f.zip | |
feat: Implement B_newstr
| -rw-r--r-- | BigInt.c | 50 | ||||
| -rw-r--r-- | example.c | 4 |
2 files changed, 51 insertions, 3 deletions
@@ -2,6 +2,7 @@ #include "MemoryManager.h" #include "Types.h" #include <limits.h> +#include <stdio.h> #include <string.h> 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) { @@ -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)); |
