Skip to content

Commit b250506

Browse files
committed
intn_bsl
Signed-off-by: Davide Bettio <davide@uninstall.it>
1 parent bac1ad9 commit b250506

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

src/libAtomVM/intn.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,74 @@ size_t intn_bxormn(const intn_digit_t m[], size_t m_len, intn_integer_sign_t m_s
550550
return res_count;
551551
}
552552

553+
#define INTN_BSL_MAX_OUT_LEN 8
554+
555+
static inline size_t size_round_to(size_t n, size_t round_to)
556+
{
557+
return (n + (round_to - 1)) & ~(round_to - 1);
558+
}
559+
560+
size_t intn_bsl(const uint32_t num[], size_t len, size_t n, uint32_t *out)
561+
{
562+
size_t digit_bit_size = sizeof(uint32_t) * 8;
563+
564+
size_t digit_left_bit_shift = n % 32;
565+
size_t right_shift_n = (32 - digit_left_bit_shift);
566+
567+
size_t counted_digits = intn_count_digits(num, len);
568+
size_t ms_digit_bits = 32 - uint32_nlz(num[counted_digits - 1]);
569+
size_t effective_bits_len = (counted_digits - 1) * digit_bit_size + ms_digit_bits;
570+
size_t new_bits_len = size_round_to(effective_bits_len + n, digit_bit_size);
571+
572+
size_t new_digits_count = new_bits_len / digit_bit_size;
573+
574+
if (new_digits_count > INTN_BSL_MAX_OUT_LEN) {
575+
return new_digits_count;
576+
}
577+
578+
size_t initial_zeros = MIN(n / digit_bit_size, INTN_BSL_MAX_OUT_LEN);
579+
memset(out, 0, initial_zeros * sizeof(uint32_t));
580+
581+
if (right_shift_n == 32) {
582+
memcpy(out + initial_zeros, num, len * sizeof(uint32_t));
583+
return initial_zeros + len;
584+
}
585+
586+
uint32_t last_digit = 0;
587+
size_t i;
588+
for (i = 0; i < counted_digits; i++) {
589+
uint32_t digit = num[i];
590+
out[initial_zeros + i] = (digit << digit_left_bit_shift) | (last_digit >> right_shift_n);
591+
last_digit = digit;
592+
}
593+
uint32_t maybe_last_out = (last_digit >> right_shift_n);
594+
595+
if (initial_zeros + i > new_digits_count) {
596+
abort();
597+
}
598+
599+
if (maybe_last_out) {
600+
out[initial_zeros + i] = maybe_last_out;
601+
return initial_zeros + i + 1;
602+
}
603+
604+
return initial_zeros + i;
605+
}
606+
607+
/*
608+
uint32_t last_digit = 0;
609+
for (size_t i = initial_zeros; i < out_len - 1; i++) {
610+
uint32_t digit = num[i - initial_zeros];
611+
if (i - initial_zeros >= counted_digits) {
612+
abort();
613+
}
614+
out[i] = (digit << digit_left_bit_shift) | (last_digit >> right_shift_n);
615+
last_digit = digit;
616+
fprintf(stderr, "in: %i, (%i), last_digit: %i\n", (int) i - initial_zeros, (int) i, (int) last_digit);
617+
}
618+
out[out_len - 1] = (last_digit >> right_shift_n);
619+
*/
620+
553621
size_t intn_count_digits(const intn_digit_t *num, size_t num_len)
554622
{
555623
int i;

0 commit comments

Comments
 (0)