|
| 1 | +% |
| 2 | +% This file is part of AtomVM. |
| 3 | +% |
| 4 | +% Copyright 2025 Davide Bettio <davide@uninstall.it> |
| 5 | +% |
| 6 | +% Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | +% you may not use this file except in compliance with the License. |
| 8 | +% You may obtain a copy of the License at |
| 9 | +% |
| 10 | +% http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | +% |
| 12 | +% Unless required by applicable law or agreed to in writing, software |
| 13 | +% distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | +% See the License for the specific language governing permissions and |
| 16 | +% limitations under the License. |
| 17 | +% |
| 18 | +% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later |
| 19 | +% |
| 20 | + |
| 21 | +-module(bigint). |
| 22 | +-export([start/0, mul/2, shrink/0, pow/2, twice/1, fact/1, get_machine_atom/0, expect_overflow/1]). |
| 23 | + |
| 24 | +start() -> |
| 25 | + test_mul(). |
| 26 | + |
| 27 | +test_mul() -> |
| 28 | + Expected_INT64_MIN = ?MODULE:pow(-2, 63), |
| 29 | + Expected_INT64_MIN = ?MODULE:shrink(), |
| 30 | + A = ?MODULE:mul(16#10101010CAFECAFE, 16#AABB), |
| 31 | + Square = ?MODULE:mul(A, A), |
| 32 | + <<"2559181265480533323615999200984578944503596644">> = erlang:integer_to_binary(Square), |
| 33 | + |
| 34 | + B = ?MODULE:mul(16#10101010CAFECAFE, 16#AABBCCDD), |
| 35 | + C = ?MODULE:mul(-(16#17322539CAFECAFE), 16#A2CBFCDD), |
| 36 | + D = ?MODULE:mul(16#19171411CAFECAFE, -(16#AF8BCCFD)), |
| 37 | + E = ?MODULE:mul(-(16#34143919CAFECAFE), -(16#8C8BCCED)), |
| 38 | + |
| 39 | + F = ?MODULE:mul(16#34143919CAFECAFE, 16#1234CAFE5678CAFE), |
| 40 | + G = ?MODULE:mul(-(16#34143919CAFECAFE), 16#1234CAFE5678CAFE), |
| 41 | + H = ?MODULE:twice(?MODULE:twice(G)), |
| 42 | + |
| 43 | + <<"3315418878780451855276287302">> = erlang:integer_to_binary(B), |
| 44 | + <<"-4565164722186152120719328582">> = erlang:integer_to_binary(C), |
| 45 | + <<"-5324687047716540217489556742">> = erlang:integer_to_binary(D), |
| 46 | + <<"8848732046695083633938421030">> = erlang:integer_to_binary(E), |
| 47 | + <<"4923137486833276011090373091921613828">> = erlang:integer_to_binary(F), |
| 48 | + <<"-4923137486833276011090373091921613828">> = erlang:integer_to_binary(G), |
| 49 | + <<"-19692549947333104044361492367686455312">> = erlang:integer_to_binary(H), |
| 50 | + |
| 51 | + 0 = ?MODULE:mul(0, E), |
| 52 | + 0 = ?MODULE:mul(0, H), |
| 53 | + |
| 54 | + INT255_MIN = ?MODULE:pow(-2, 255), |
| 55 | + ok = ?MODULE:expect_overflow(fun() -> ?MODULE:twice(INT255_MIN) end), |
| 56 | + ok = ?MODULE:expect_overflow(fun() -> ?MODULE:mul(INT255_MIN, -1) end), |
| 57 | + ok = ?MODULE:expect_overflow(fun() -> ?MODULE:mul(-1, INT255_MIN) end), |
| 58 | + <<"-57896044618658097711785492504343953926634992332820282019728792003956564819968">> = erlang:integer_to_binary( |
| 59 | + INT255_MIN |
| 60 | + ), |
| 61 | + erlang:display(INT255_MIN), |
| 62 | + |
| 63 | + Fact55 = ?MODULE:fact(55), |
| 64 | + <<"12696403353658275925965100847566516959580321051449436762275840000000000000">> = erlang:integer_to_binary( |
| 65 | + Fact55 |
| 66 | + ), |
| 67 | + |
| 68 | + ?MODULE:mul(0, INT255_MIN) + ?MODULE:mul(INT255_MIN, 0). |
| 69 | + |
| 70 | +mul(A, B) -> |
| 71 | + A * B. |
| 72 | + |
| 73 | +shrink() -> |
| 74 | + S1 = ?MODULE:mul(4611686018427387904, 2), |
| 75 | + S2 = ?MODULE:mul(-1, S1), |
| 76 | + S2. |
| 77 | + |
| 78 | +pow(_A, 0) -> |
| 79 | + 1; |
| 80 | +pow(A, N) -> |
| 81 | + A * pow(A, N - 1). |
| 82 | + |
| 83 | +twice(N) -> |
| 84 | + 2 * N. |
| 85 | + |
| 86 | +fact(0) -> |
| 87 | + 1; |
| 88 | +fact(N) when N rem 2 == 0 -> |
| 89 | + N * fact(N - 1); |
| 90 | +fact(N) when N rem 2 == 1 -> |
| 91 | + fact(N - 1) * N. |
| 92 | + |
| 93 | +expect_overflow(OvfFun) -> |
| 94 | + Machine = ?MODULE:get_machine_atom(), |
| 95 | + try {Machine, OvfFun()} of |
| 96 | + {beam, I} when is_integer(I) -> ok; |
| 97 | + {atomvm, Result} -> {unexpected_result, Result} |
| 98 | + catch |
| 99 | + error:overflow -> ok; |
| 100 | + _:E -> {unexpected_error, E} |
| 101 | + end. |
| 102 | + |
| 103 | +get_machine_atom() -> |
| 104 | + case erlang:system_info(machine) of |
| 105 | + "BEAM" -> beam; |
| 106 | + _ -> atomvm |
| 107 | + end. |
0 commit comments