Skip to content

Commit 48c8624

Browse files
committed
Merge pull request #1934 from bettio/bif-bigint-cleanup
bif.c bigint cleanup Move functions & rename variables (to understandable names). Continuation of #1933 These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents 014c48b + 7946e89 commit 48c8624

File tree

1 file changed

+103
-108
lines changed

1 file changed

+103
-108
lines changed

src/libAtomVM/bif.c

Lines changed: 103 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,6 @@
7979
#define INT64_MAX_AS_AVM_FLOAT 9223372036854775295.0 // 0x43DFFFFFFFFFFFFF = 2^62 * 1.1...1b
8080
#endif
8181

82-
static term make_bigint(Context *ctx, uint32_t fail_label, uint32_t live,
83-
const intn_digit_t bigres[], size_t bigres_len, intn_integer_sign_t sign);
84-
85-
static void conv_term_to_bigint(term arg1, intn_digit_t *tmp_buf1, const intn_digit_t **b1,
86-
size_t *b1_len, intn_integer_sign_t *b1_sign);
87-
8882
const struct ExportedFunction *bif_registry_get_handler(const char *mfa)
8983
{
9084
const BifNameAndPtr *nameAndPtr = in_word_set(mfa, strlen(mfa));
@@ -530,6 +524,56 @@ static inline term make_maybe_boxed_int64(Context *ctx, uint32_t fail_label, uin
530524
}
531525
#endif
532526

527+
// this function assumes that bigres_len is always <= bigres buffer capacity
528+
static term make_bigint(Context *ctx, uint32_t fail_label, uint32_t live,
529+
const intn_digit_t bigres[], size_t bigres_len, intn_integer_sign_t sign)
530+
{
531+
size_t count = intn_count_digits(bigres, bigres_len);
532+
533+
if (UNLIKELY(count > INTN_MAX_IN_LEN)) {
534+
RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM);
535+
}
536+
537+
if (!intn_fits_int64(bigres, count, sign)) {
538+
size_t intn_data_size;
539+
size_t rounded_res_len;
540+
term_bigint_size_requirements(count, &intn_data_size, &rounded_res_len);
541+
542+
if (UNLIKELY(memory_ensure_free_with_roots(
543+
ctx, BOXED_BIGINT_HEAP_SIZE(intn_data_size), live, ctx->x, MEMORY_CAN_SHRINK)
544+
!= MEMORY_GC_OK)) {
545+
RAISE_ERROR_BIF(fail_label, OUT_OF_MEMORY_ATOM);
546+
}
547+
548+
term bigres_term = term_create_uninitialized_bigint(
549+
intn_data_size, (term_integer_sign_t) sign, &ctx->heap);
550+
term_initialize_bigint(bigres_term, bigres, count, rounded_res_len);
551+
552+
return bigres_term;
553+
} else {
554+
int64_t res64 = intn_to_int64(bigres, count, sign);
555+
#if BOXED_TERMS_REQUIRED_FOR_INT64 > 1
556+
return make_maybe_boxed_int64(ctx, fail_label, live, res64);
557+
#else
558+
return make_maybe_boxed_int(ctx, fail_label, live, res64);
559+
#endif
560+
}
561+
}
562+
563+
static void conv_term_to_bigint(term t, intn_digit_t *tmp_buf, const intn_digit_t **bigint,
564+
size_t *bigint_len, intn_integer_sign_t *bigint_sign)
565+
{
566+
if (term_is_bigint(t)) {
567+
term_to_bigint(t, bigint, bigint_len, bigint_sign);
568+
569+
} else {
570+
avm_int64_t i64 = term_maybe_unbox_int64(t);
571+
intn_from_int64(i64, tmp_buf, bigint_sign);
572+
*bigint = tmp_buf;
573+
*bigint_len = INTN_INT64_LEN;
574+
}
575+
}
576+
533577
static term add_int64_to_bigint(
534578
Context *ctx, uint32_t fail_label, uint32_t live, int64_t val1, int64_t val2)
535579
{
@@ -546,23 +590,23 @@ static term add_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
546590
intn_digit_t tmp_buf1[INTN_INT64_LEN];
547591
intn_digit_t tmp_buf2[INTN_INT64_LEN];
548592

549-
const intn_digit_t *bn1;
550-
size_t bn1_len;
551-
intn_integer_sign_t bn1_sign;
552-
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
553-
const intn_digit_t *bn2;
554-
size_t bn2_len;
555-
intn_integer_sign_t bn2_sign;
556-
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
593+
const intn_digit_t *big1;
594+
size_t big1_len;
595+
intn_integer_sign_t big1_sign;
596+
conv_term_to_bigint(arg1, tmp_buf1, &big1, &big1_len, &big1_sign);
597+
const intn_digit_t *big2;
598+
size_t big2_len;
599+
intn_integer_sign_t big2_sign;
600+
conv_term_to_bigint(arg2, tmp_buf2, &big2, &big2_len, &big2_sign);
557601

558-
size_t bigres_len = INTN_ADD_OUT_LEN(bn1_len, bn2_len);
602+
size_t bigres_len = INTN_ADD_OUT_LEN(big1_len, big2_len);
559603
if (bigres_len > INTN_MAX_RES_LEN) {
560604
RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM);
561605
}
562606

563607
intn_digit_t bigres[INTN_MAX_RES_LEN];
564608
intn_integer_sign_t res_sign;
565-
bigres_len = intn_add(bn1, bn1_len, bn1_sign, bn2, bn2_len, bn2_sign, bigres, &res_sign);
609+
bigres_len = intn_add(big1, big1_len, big1_sign, big2, big2_len, big2_sign, bigres, &res_sign);
566610

567611
return make_bigint(ctx, fail_label, live, bigres, bigres_len, res_sign);
568612
}
@@ -684,23 +728,23 @@ static term sub_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
684728
intn_digit_t tmp_buf1[INTN_INT64_LEN];
685729
intn_digit_t tmp_buf2[INTN_INT64_LEN];
686730

687-
const intn_digit_t *bn1;
688-
size_t bn1_len;
689-
intn_integer_sign_t bn1_sign;
690-
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
691-
const intn_digit_t *bn2;
692-
size_t bn2_len;
693-
intn_integer_sign_t bn2_sign;
694-
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
731+
const intn_digit_t *big1;
732+
size_t big1_len;
733+
intn_integer_sign_t big1_sign;
734+
conv_term_to_bigint(arg1, tmp_buf1, &big1, &big1_len, &big1_sign);
735+
const intn_digit_t *big2;
736+
size_t big2_len;
737+
intn_integer_sign_t big2_sign;
738+
conv_term_to_bigint(arg2, tmp_buf2, &big2, &big2_len, &big2_sign);
695739

696-
size_t bigres_len = INTN_SUB_OUT_LEN(bn1_len, bn2_len);
740+
size_t bigres_len = INTN_SUB_OUT_LEN(big1_len, big2_len);
697741
if (bigres_len > INTN_MAX_RES_LEN) {
698742
RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM);
699743
}
700744

701745
intn_digit_t bigres[INTN_MAX_RES_LEN];
702746
intn_integer_sign_t res_sign;
703-
bigres_len = intn_sub(bn1, bn1_len, bn1_sign, bn2, bn2_len, bn2_sign, bigres, &res_sign);
747+
bigres_len = intn_sub(big1, big1_len, big1_sign, big2, big2_len, big2_sign, bigres, &res_sign);
704748

705749
return make_bigint(ctx, fail_label, live, bigres, bigres_len, res_sign);
706750
}
@@ -796,56 +840,6 @@ term bif_erlang_sub_2(Context *ctx, uint32_t fail_label, int live, term arg1, te
796840
}
797841
}
798842

799-
// this function assumes that bigres_len is always <= bigres buffer capacity
800-
static term make_bigint(Context *ctx, uint32_t fail_label, uint32_t live,
801-
const intn_digit_t bigres[], size_t bigres_len, intn_integer_sign_t sign)
802-
{
803-
size_t count = intn_count_digits(bigres, bigres_len);
804-
805-
if (UNLIKELY(count > INTN_MAX_IN_LEN)) {
806-
RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM);
807-
}
808-
809-
if (!intn_fits_int64(bigres, count, sign)) {
810-
size_t intn_data_size;
811-
size_t rounded_res_len;
812-
term_bigint_size_requirements(count, &intn_data_size, &rounded_res_len);
813-
814-
if (UNLIKELY(memory_ensure_free_with_roots(
815-
ctx, BOXED_BIGINT_HEAP_SIZE(intn_data_size), live, ctx->x, MEMORY_CAN_SHRINK)
816-
!= MEMORY_GC_OK)) {
817-
RAISE_ERROR_BIF(fail_label, OUT_OF_MEMORY_ATOM);
818-
}
819-
820-
term bigres_term = term_create_uninitialized_bigint(
821-
intn_data_size, (term_integer_sign_t) sign, &ctx->heap);
822-
term_initialize_bigint(bigres_term, bigres, count, rounded_res_len);
823-
824-
return bigres_term;
825-
} else {
826-
int64_t res64 = intn_to_int64(bigres, count, sign);
827-
#if BOXED_TERMS_REQUIRED_FOR_INT64 > 1
828-
return make_maybe_boxed_int64(ctx, fail_label, live, res64);
829-
#else
830-
return make_maybe_boxed_int(ctx, fail_label, live, res64);
831-
#endif
832-
}
833-
}
834-
835-
static void conv_term_to_bigint(term arg1, intn_digit_t *tmp_buf1, const intn_digit_t **b1,
836-
size_t *b1_len, intn_integer_sign_t *b1_sign)
837-
{
838-
if (term_is_bigint(arg1)) {
839-
term_to_bigint(arg1, b1, b1_len, b1_sign);
840-
841-
} else {
842-
avm_int64_t i64 = term_maybe_unbox_int64(arg1);
843-
intn_from_int64(i64, tmp_buf1, b1_sign);
844-
*b1 = tmp_buf1;
845-
*b1_len = INTN_INT64_LEN;
846-
}
847-
}
848-
849843
static term mul_int64_to_bigint(
850844
Context *ctx, uint32_t fail_label, uint32_t live, int64_t val1, int64_t val2)
851845
{
@@ -862,23 +856,23 @@ static term mul_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
862856
intn_digit_t tmp_buf1[INTN_INT64_LEN];
863857
intn_digit_t tmp_buf2[INTN_INT64_LEN];
864858

865-
const intn_digit_t *bn1;
866-
size_t bn1_len;
867-
intn_integer_sign_t bn1_sign;
868-
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
869-
const intn_digit_t *bn2;
870-
size_t bn2_len;
871-
intn_integer_sign_t bn2_sign;
872-
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
859+
const intn_digit_t *big1;
860+
size_t big1_len;
861+
intn_integer_sign_t big1_sign;
862+
conv_term_to_bigint(arg1, tmp_buf1, &big1, &big1_len, &big1_sign);
863+
const intn_digit_t *big2;
864+
size_t big2_len;
865+
intn_integer_sign_t big2_sign;
866+
conv_term_to_bigint(arg2, tmp_buf2, &big2, &big2_len, &big2_sign);
873867

874-
size_t bigres_len = INTN_MUL_OUT_LEN(bn1_len, bn2_len);
868+
size_t bigres_len = INTN_MUL_OUT_LEN(big1_len, big2_len);
875869
if (bigres_len > INTN_MAX_RES_LEN) {
876870
RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM);
877871
}
878872

879873
intn_digit_t bigres[INTN_MAX_RES_LEN];
880874
intn_integer_sign_t res_sign;
881-
intn_mul(bn1, bn1_len, bn1_sign, bn2, bn2_len, bn2_sign, bigres, &res_sign);
875+
intn_mul(big1, big1_len, big1_sign, big2, big2_len, big2_sign, bigres, &res_sign);
882876

883877
return make_bigint(ctx, fail_label, live, bigres, bigres_len, res_sign);
884878
}
@@ -1026,27 +1020,28 @@ static term div_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
10261020
intn_digit_t tmp_buf1[INTN_INT64_LEN];
10271021
intn_digit_t tmp_buf2[INTN_INT64_LEN];
10281022

1029-
const intn_digit_t *bn1;
1030-
size_t bn1_len;
1031-
intn_integer_sign_t bn1_sign;
1032-
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
1033-
const intn_digit_t *bn2;
1034-
size_t bn2_len;
1035-
intn_integer_sign_t bn2_sign;
1036-
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
1023+
const intn_digit_t *big1;
1024+
size_t big1_len;
1025+
intn_integer_sign_t big1_sign;
1026+
conv_term_to_bigint(arg1, tmp_buf1, &big1, &big1_len, &big1_sign);
1027+
const intn_digit_t *big2;
1028+
size_t big2_len;
1029+
intn_integer_sign_t big2_sign;
1030+
conv_term_to_bigint(arg2, tmp_buf2, &big2, &big2_len, &big2_sign);
10371031

1038-
int cmp_result = intn_cmp(bn1, bn1_len, bn2, bn2_len);
1032+
int cmp_result = intn_cmp(big1, big1_len, big2, big2_len);
10391033
if (cmp_result < 0) {
10401034
// a / b when a < b -> always 0
10411035
return term_from_int(0);
10421036
} else if (cmp_result == 0) {
10431037
// a / b when a == b -> always +-1
1044-
return (bn1_sign == bn2_sign) ? term_from_int(1) : term_from_int(-1);
1038+
return (big1_sign == big2_sign) ? term_from_int(1) : term_from_int(-1);
10451039
}
10461040

10471041
intn_digit_t bigres[INTN_MAX_RES_LEN];
10481042
intn_integer_sign_t res_sign;
1049-
size_t bigres_len = intn_div(bn1, bn1_len, bn1_sign, bn2, bn2_len, bn2_sign, bigres, &res_sign, NULL, NULL);
1043+
size_t bigres_len = intn_div(
1044+
big1, big1_len, big1_sign, big2, big2_len, big2_sign, bigres, &res_sign, NULL, NULL);
10501045

10511046
return make_bigint(ctx, fail_label, live, bigres, bigres_len, res_sign);
10521047
}
@@ -1348,16 +1343,16 @@ static term rem_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
13481343
intn_digit_t tmp_buf1[INTN_INT64_LEN];
13491344
intn_digit_t tmp_buf2[INTN_INT64_LEN];
13501345

1351-
const intn_digit_t *bn1;
1352-
size_t bn1_len;
1353-
intn_integer_sign_t bn1_sign;
1354-
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
1355-
const intn_digit_t *bn2;
1356-
size_t bn2_len;
1357-
intn_integer_sign_t bn2_sign;
1358-
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
1346+
const intn_digit_t *big1;
1347+
size_t big1_len;
1348+
intn_integer_sign_t big1_sign;
1349+
conv_term_to_bigint(arg1, tmp_buf1, &big1, &big1_len, &big1_sign);
1350+
const intn_digit_t *big2;
1351+
size_t big2_len;
1352+
intn_integer_sign_t big2_sign;
1353+
conv_term_to_bigint(arg2, tmp_buf2, &big2, &big2_len, &big2_sign);
13591354

1360-
int cmp_result = intn_cmp(bn1, bn1_len, bn2, bn2_len);
1355+
int cmp_result = intn_cmp(big1, big1_len, big2, big2_len);
13611356
if (cmp_result < 0) {
13621357
// a rem b when |a| < |b| -> always a
13631358
return arg1;
@@ -1369,9 +1364,9 @@ static term rem_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
13691364
intn_digit_t q[INTN_MAX_RES_LEN];
13701365
intn_digit_t bigres[INTN_MAX_RES_LEN];
13711366
size_t bigres_len;
1372-
intn_divu(bn1, bn1_len, bn2, bn2_len, q, bigres, &bigres_len);
1367+
intn_divu(big1, big1_len, big2, big2_len, q, bigres, &bigres_len);
13731368

1374-
return make_bigint(ctx, fail_label, live, bigres, bigres_len, bn1_sign);
1369+
return make_bigint(ctx, fail_label, live, bigres, bigres_len, big1_sign);
13751370
}
13761371

13771372
static term rem_boxed_helper(Context *ctx, uint32_t fail_label, uint32_t live, term arg1, term arg2)

0 commit comments

Comments
 (0)