diff options
Diffstat (limited to 'BigInt.c')
| -rw-r--r-- | BigInt.c | 50 |
1 files changed, 47 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) { |
