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-
8882const 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+
533577static 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-
849843static 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
13771372static term rem_boxed_helper (Context * ctx , uint32_t fail_label , uint32_t live , term arg1 , term arg2 )
0 commit comments