aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BigInt.c38
1 files changed, 23 insertions, 15 deletions
diff --git a/BigInt.c b/BigInt.c
index e0014cc..b19d3e6 100644
--- a/BigInt.c
+++ b/BigInt.c
@@ -382,23 +382,19 @@ B_tostr(MemoryManager *mm, BigInt intx) {
return str;
}
- // TODO: these calculations are based on Wikipedia's statement that
- // "4 x ceil(n / 3)" is enough bits of memory.
- // This is true, but it grows faster than needed, so from 31 bits onward,
- // we use too much memory (adding unnecessary leading 0s).
- // The exact value is "ceil(log10(2^x - 1))"
+ // The exact amount of necessary bcd bits is "ceil(log10(2^x - 1))",
+ // however this is difficult to compute.
+ // Wikipedia offers a convenient approximation "4 x ceil(n / 3)",
+ // which grows faster than the true formula. Simplifying and calculating
+ // for number of bytes, results in the following formula value.
+ // Do note, a side effect is that we'll use more memory than needed and
+ // show unnecessary leading 0s. Later in the code we'll discard these zeroes.
usize bcd_bytes = 1 + (n - 1) / 6;
- int odd_nibbles = (1 + (n - 1) / 3) % 2;
-
- char *str;
- if (R_Ok != mm->alloc(*mm, (void**)&str, sizeof(char) * (bcd_bytes * 2 - odd_nibbles + 1)))
- return NULL;
u8 *bcd;
- if (R_Ok != mm->alloc(*mm, (void**)&bcd, sizeof(u8) * bcd_bytes)) {
- mm->free(*mm, (void**)&str);
+ if (R_Ok != mm->alloc(*mm, (void**)&bcd, sizeof(u8) * bcd_bytes))
return NULL;
- }
+
memset(bcd, 0, sizeof(u8) * bcd_bytes);
UWord mask = (UWord)1 << (UWORD_BIT - 1);
@@ -430,12 +426,24 @@ B_tostr(MemoryManager *mm, BigInt intx) {
}
}
+ // Remove leading zeroes
+ while (bcd_bytes > 1 && bcd[bcd_bytes - 1] == 0)
+ --bcd_bytes;
+
+ int skip_nibble = (bcd[bcd_bytes - 1] & 0b11110000) == 0;
+
+ char *str;
+ if (R_Ok != mm->alloc(*mm, (void**)&str, sizeof(char) * (bcd_bytes * 2 - skip_nibble + 1))) {
+ mm->free(*mm, (void**)&bcd);
+ return NULL;
+ }
+
// BCD to char string
char *s = str;
- if (!odd_nibbles)
+ if (!skip_nibble)
*(s++) = ((bcd[bcd_bytes - 1] & 0b11110000) >> 4) + '0';
- *(s++) = (bcd[bcd_bytes - 1] & 0b00001111) + '0';
+ *(s++) = (bcd[bcd_bytes - 1] & 0b00001111) + '0';
for (usize b = bcd_bytes - 2; b < bcd_bytes; --b) {
*(s++) = ((bcd[b] & 0b11110000) >> 4) + '0';