diff options
Diffstat (limited to 'BigInt.c')
| -rw-r--r-- | BigInt.c | 89 |
1 files changed, 89 insertions, 0 deletions
@@ -74,6 +74,11 @@ B_newstr(MemoryManager *mm, const char* str) { } BigInt +B_newbytes(MemoryManager *mm, usize bytes) { + return B_start(mm, 1 + (bytes - 1) / sizeof(UWord)); +} + +BigInt B_dup(MemoryManager *mm, BigInt bigint) { if (NULL == bigint) return NULL; @@ -196,6 +201,90 @@ B_sub(BigInt *inta, BigInt intb) { return R_Ok; } +Result +B_rshift(BigInt *intx, usize shift) { + if (NULL == intx || NULL == *intx) + return R_NullArgument; + + if (shift == 0) + return R_Ok; + + struct BigIntMeta *bim = B_metadata(*intx); + UWord *x = *intx; + + usize word_moves = shift / (sizeof(UWord) * 8); + if (word_moves) { + usize w = 0; + for (; w < bim->words - word_moves; ++w) + x[w] = x[w + word_moves]; + for (; w < bim->words; ++w) + x[w] = 0; + } + + usize bit_moves = shift % (sizeof(UWord) * 8); + if (bit_moves == 1) { + x[0] >>= 1; + for (usize w = 1; w < bim->words; ++w) { + x[w - 1] |= (x[w] & 1) << (sizeof(UWord) * 8 - 1); + x[w] >>= 1; + } + } + else if (bit_moves > 1) { + UWord mask = ((UWord)1 << bit_moves) - 1; + + x[0] >>= bit_moves; + for (usize w = 1; w < bim->words; ++w) { + x[w - 1] |= (x[w] & mask) << (sizeof(UWord) * 8 - bit_moves); + x[w] >>= bit_moves; + } + } + + return R_Ok; +} + +Result +B_lshift(BigInt *intx, usize shift) { + if (NULL == intx || NULL == *intx) + return R_NullArgument; + + if (shift == 0) + return R_Ok; + + struct BigIntMeta *bim = B_metadata(*intx); + UWord *x = *intx; + + usize word_moves = shift / (sizeof(UWord) * 8); + if (word_moves) { + usize w = bim->words - 1; + for (; w >= word_moves; --w) + x[w] = x[w - word_moves]; + for (; w < bim->words; --w) + x[w] = 0; + } + + usize bit_moves = shift % (sizeof(UWord) * 8); + if (bit_moves == 1) { + UWord mask = (UWord)1 << (sizeof(UWord) * 8 - 1); + + x[bim->words - 1] <<= 1; + for (usize w = bim->words - 2; w < bim->words; --w) { + x[w + 1] |= (x[w] & mask) >> (sizeof(UWord) * 8 - 1); + x[w] <<= 1; + } + } + else if (bit_moves > 1) { + UWord mask = (((UWord)1 << bit_moves) - 1) << (sizeof(UWord) * 8 - bit_moves); + + x[bim->words - 1] <<= bit_moves; + for (usize w = bim->words - 2; w < bim->words; --w) { + x[w + 1] |= (x[w] & mask) >> (sizeof(UWord) * 8 - bit_moves); + x[w] <<= bit_moves; + } + } + + return R_Ok; +} + /* Get */ usize |
