Skip to content

Commit eb7b64b

Browse files
committed
WIP bormn
Signed-off-by: Davide Bettio <davide@uninstall.it>
1 parent 003255a commit eb7b64b

File tree

2 files changed

+167
-1
lines changed

2 files changed

+167
-1
lines changed

src/libAtomVM/intn.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,107 @@ size_t intn_addmnu(
380380
return i;
381381
}
382382

383+
static void cond_neg(
384+
intn_integer_sign_t sign, const intn_digit_t in[], size_t in_len, intn_digit_t out[])
385+
{
386+
if (sign == IntNPositiveInteger) {
387+
memcpy(out, in, sizeof(intn_digit_t) * in_len);
388+
} else {
389+
uint32_t carry = 1;
390+
for (size_t i = 0; i < in_len; i++) {
391+
uint64_t temp = (uint64_t) (~in[i]) + (uint64_t) carry;
392+
out[i] = (uint32_t) temp;
393+
carry = temp >> 32;
394+
}
395+
}
396+
}
397+
398+
static size_t prepare_out(const intn_digit_t m[], size_t m_len, intn_integer_sign_t m_sign,
399+
const intn_digit_t n[], size_t n_len, intn_integer_sign_t n_sign, const intn_digit_t *b[],
400+
size_t *b_len, intn_integer_sign_t *b_sign, intn_digit_t out[])
401+
{
402+
const intn_digit_t *longest;
403+
size_t longest_len;
404+
intn_integer_sign_t longest_sign;
405+
406+
if (m_len > n_len) {
407+
longest = m;
408+
longest_len = m_len;
409+
longest_sign = m_sign;
410+
*b = n;
411+
*b_len = n_len;
412+
*b_sign = n_sign;
413+
} else {
414+
longest = n;
415+
longest_len = n_len;
416+
longest_sign = n_sign;
417+
*b = m;
418+
*b_len = m_len;
419+
*b_sign = m_sign;
420+
}
421+
422+
cond_neg(longest_sign, longest, longest_len, out);
423+
if (longest_sign == IntNPositiveInteger) {
424+
out[longest_len] = 0;
425+
} else {
426+
out[longest_len] = UINT32_MAX;
427+
}
428+
return longest_len + 1;
429+
}
430+
431+
static inline uint32_t bit_op(uint32_t a, uint32_t b) { return a | b; }
432+
433+
static inline size_t neg_and_bitwise(const intn_digit_t b[], size_t b_len,
434+
intn_integer_sign_t b_sign, intn_digit_t out[], size_t out_len)
435+
{
436+
if (b_sign == IntNPositiveInteger) {
437+
for (size_t i = 0; i < b_len; i++) {
438+
out[i] = bit_op(out[i], b[i]);
439+
}
440+
for (size_t i = b_len; i < out_len; i++) {
441+
out[i] = bit_op(out[i], 0);
442+
}
443+
} else {
444+
uint32_t carry = 1;
445+
for (size_t i = 0; i < b_len; i++) {
446+
uint64_t temp = (uint64_t) (~b[i]) + (uint64_t) carry;
447+
out[i] = bit_op(out[i], (uint32_t) temp);
448+
carry = temp >> 32;
449+
}
450+
if (b_len < out_len) {
451+
out[b_len] = bit_op(out[b_len], (UINT32_MAX) + carry);
452+
}
453+
for (size_t i = b_len + 1; i < out_len; i++) {
454+
out[i] = bit_op(out[i], UINT32_MAX);
455+
}
456+
}
457+
return out_len;
458+
}
459+
460+
size_t intn_bormn(const intn_digit_t m[], size_t m_len, intn_integer_sign_t m_sign,
461+
const intn_digit_t n[], size_t n_len, intn_integer_sign_t n_sign, intn_digit_t out[],
462+
intn_integer_sign_t *out_sign)
463+
{
464+
intn_digit_t working_buf[INTN_MAX_IN_LEN + 1];
465+
466+
const intn_digit_t *b;
467+
size_t b_len;
468+
intn_integer_sign_t b_sign;
469+
470+
size_t count
471+
= prepare_out(m, m_len, m_sign, n, n_len, n_sign, &b, &b_len, &b_sign, working_buf);
472+
473+
neg_and_bitwise(b, b_len, b_sign, working_buf, count);
474+
475+
*out_sign = (intn_integer_sign_t) ((unsigned int) m_sign | (unsigned int) n_sign)
476+
& IntNNegativeInteger;
477+
478+
size_t ret_count = count; // MAX(count, count2);
479+
cond_neg(*out_sign, working_buf, ret_count, out);
480+
481+
return ret_count;
482+
}
483+
383484
size_t intn_count_digits(const intn_digit_t *num, size_t num_len)
384485
{
385486
int i;

tests/erlang_tests/bigint.erl

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ start() ->
5353
conv_to_from_float() +
5454
external_term_decode() +
5555
big_literals() +
56-
to_external_term().
56+
to_external_term() +
57+
test_bor().
5758

5859
test_mul() ->
5960
Expected_INT64_MIN = ?MODULE:pow(-2, 63),
@@ -790,6 +791,70 @@ to_external_term() ->
790791

791792
0.
792793

794+
test_bor() ->
795+
Pattern1 = erlang:binary_to_integer(
796+
?MODULE:id(
797+
<<"10101010101010101010101010101010101010101010101010101010101010100000000000000000">>
798+
),
799+
2
800+
),
801+
Pattern2 = erlang:binary_to_integer(
802+
?MODULE:id(
803+
<<"1010101010101010101010101010101010101010101010101010101010101010000000000000000">>
804+
),
805+
2
806+
),
807+
Res1 = erlang:binary_to_integer(
808+
?MODULE:id(
809+
<<"11111111111111111111111111111111111111111111111111111111111111110000000000000000">>
810+
),
811+
2
812+
),
813+
Res1 = Pattern1 bor Pattern2,
814+
815+
Pattern3 = erlang:binary_to_integer(?MODULE:id(<<"-1">>), 2),
816+
Res2 = ?MODULE:id(-1),
817+
Res2 = Pattern1 bor Pattern3,
818+
819+
Pattern4 = erlang:binary_to_integer(?MODULE:id(<<"-5555555511111111123456789ABCDEF0">>), 16),
820+
Pattern5 = erlang:binary_to_integer(?MODULE:id(<<"+30303030333333333111111111111111">>), 16),
821+
Res3 = erlang:binary_to_integer(?MODULE:id(<<"-4545454500000000022446688AACCEEF">>), 16),
822+
Res3 = Pattern4 bor Pattern5,
823+
824+
Pattern6 = erlang:binary_to_integer(?MODULE:id(<<"-30303030333333333111111111111111">>), 16),
825+
Res4 = erlang:binary_to_integer(?MODULE:id(<<"-10101010111111111010101010101001">>), 16),
826+
Res4 = Pattern4 bor Pattern6,
827+
828+
Pattern7 = erlang:binary_to_integer(
829+
?MODULE:id(<<"-8000000000000000000000000000000000000000000000000000000000000000">>), 16
830+
),
831+
Res5 = ?MODULE:id(-1),
832+
Res5 = ?MODULE:id(Pattern7) bor ?MODULE:id(-1),
833+
834+
Res6 = Pattern4,
835+
Res6 = ?MODULE:id(Pattern4) bor ?MODULE:id(Pattern7),
836+
837+
Res7 = erlang:binary_to_integer(
838+
?MODULE:id(<<"-7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF">>), 16
839+
),
840+
Res7 = ?MODULE:id(Pattern7) bor ?MODULE:id(1),
841+
842+
Pattern8 = erlang:binary_to_integer(
843+
?MODULE:id(<<"5555555555555555555555555555555555555555555555555555555555555555">>), 16
844+
),
845+
Pattern9 = erlang:binary_to_integer(
846+
?MODULE:id(<<"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA">>), 16
847+
),
848+
Res8 = erlang:binary_to_integer(
849+
?MODULE:id(<<"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF">>), 16
850+
),
851+
Res8 = Pattern8 bor Pattern9,
852+
853+
Res9 = ?MODULE:id(-1),
854+
Res9 = ?MODULE:id(-1) bor Res8,
855+
856+
0.
857+
793858
id(X) ->
794859
X.
795860

0 commit comments

Comments
 (0)