Skip to content

Commit

Permalink
Add Math.bigint in SC (#1550)
Browse files Browse the repository at this point in the history
* Add Math.bigint in SC

* Math.bigint always return an integer or raise

---------

Co-authored-by: bchamagne <[email protected]>
  • Loading branch information
samuelmanzanera and bchamagne authored Aug 20, 2024
1 parent a53a328 commit f7ebcd2
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
50 changes: 50 additions & 0 deletions lib/archethic/contracts/interpreter/library/common/math.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Math do

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.ASTHelper, as: AST
alias Archethic.Contracts.Interpreter.Library

use Tag
import Bitwise
Expand Down Expand Up @@ -127,6 +128,50 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Math do
to_number(res, is_integer(num1) and is_integer(num2))
end

@doc """
## Example
iex> Math.bigint(49.85024327, 18)
49_850_243_270_000_000_000
iex> Math.bigint(1.994e-4, 18)
199_400_000_000_000
iex> Math.bigint(0.19941234, 18)
199_412_340_000_000_000
iex> Math.bigint(0.10000006, 18)
100_000_060_000_000_000
iex> Math.bigint(0.002, 18)
2_000_000_000_000_000
iex> Math.bigint(1.2390131, 18)
1_239_013_100_000_000_000
iex> Math.bigint(10, 18)
10_000_000_000_000_000_000
iex> Math.bigint(1, 8)
100_000_000
"""
@spec bigint(num :: number(), decimals :: number()) :: number()
def bigint(num, decimals) do
num
|> to_string()
|> Decimal.new()
|> Decimal.mult(Decimal.new(10 ** decimals))
|> then(fn dec ->
if Decimal.integer?(dec) do
Decimal.to_integer(dec)
else
raise Library.Error, message: "Number exceeds decimals"
end
end)
end

@spec check_types(atom(), list()) :: boolean()
def check_types(:trunc, [first]) do
AST.is_number?(first) || AST.is_variable_or_function_call?(first)
Expand All @@ -146,6 +191,11 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Math do
(AST.is_number?(second) || AST.is_variable_or_function_call?(second))
end

def check_types(:bigint, [first, second]) do
(AST.is_number?(first) || AST.is_variable_or_function_call?(first)) &&
(AST.is_number?(second) || AST.is_variable_or_function_call?(second))
end

def check_types(_, _), do: false

defp to_decimal(num) when is_integer(num), do: Decimal.new(num)
Expand Down
11 changes: 11 additions & 0 deletions test/archethic/contracts/interpreter/library/common/math_test.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
defmodule Archethic.Contracts.Interpreter.Library.Common.MathTest do
use ArchethicCase

alias Archethic.Contracts.Interpreter.Library
alias Archethic.Contracts.Interpreter.Library.Common.Math

doctest Math

test "exceed decimals raise" do
assert_raise Library.Error, "Number exceeds decimals", fn ->
Math.bigint(0.1234, 2)
end

assert_raise Library.Error, "Number exceeds decimals", fn ->
Math.bigint(0.12345874564, 8)
end
end
end

0 comments on commit f7ebcd2

Please sign in to comment.