aboutsummaryrefslogtreecommitdiff
path: root/BigInt.c
diff options
context:
space:
mode:
Diffstat (limited to 'BigInt.c')
-rw-r--r--BigInt.c50
1 files changed, 47 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 <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) {