Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logarithm & ManagedDecimal cleanup #1670

Merged
merged 40 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6fcfd36
ln impl and test
mihaicalinluca Jun 3, 2024
72327d3
ln alg decimals fix
alyn509 Jun 4, 2024
f9ea270
test fix
mihaicalinluca Jun 5, 2024
38cbf08
Merge pull request #1675 from multiversx/ln-alg-fix
mihaicalinluca Jun 5, 2024
ca2d88f
added macros, changed ln to use managed decimal instead of big float,…
mihaicalinluca Jun 10, 2024
4ee2bb3
reorg, separated impl in 2 new files, added add assign and sub assign…
mihaicalinluca Jun 18, 2024
6de200d
proc macros in derive and tests
mihaicalinluca Jun 18, 2024
2746c23
build fix
mihaicalinluca Jun 18, 2024
a7d1186
Merge branch 'rc/v0.51' into mng-dec-log-root
andrei-marinica Jun 21, 2024
6253b4a
logarithm refactor
andrei-marinica Jun 22, 2024
3820924
managed decimal reorg
andrei-marinica Jun 22, 2024
3e42242
managed decimal reorg
andrei-marinica Jun 22, 2024
8cca4a9
managed decimal ln - basic impl
andrei-marinica Jun 24, 2024
f00c4cb
Merge branch 'rc/v0.51' into mng-dec-log-root
andrei-marinica Jun 25, 2024
6d5082b
ManagedDecimalSigned - initial implementation
andrei-marinica Jun 26, 2024
7b87b90
ManagedDecimal operators refactor
andrei-marinica Jun 27, 2024
4f69193
ManagedDecimalSigned operators
andrei-marinica Jun 27, 2024
f4e0024
ManagedDecimal - moved ln
andrei-marinica Jun 27, 2024
137861f
ManagedBuffer - ln cleanup, conversions
andrei-marinica Jun 27, 2024
15aff5b
BigUint log2_floor refactor, test fixes
andrei-marinica Jun 28, 2024
292867d
test fix
andrei-marinica Jun 28, 2024
b1d0ff8
Managed Decimal into signed cleanup
andrei-marinica Jun 28, 2024
faa371a
rust docs
andrei-marinica Jun 28, 2024
a35a8c3
cleaned up some inlines
andrei-marinica Jun 28, 2024
c0e73fa
test for ln
mihaicalinluca Jul 1, 2024
5c94a8d
arithmetic op - managed decimal signed
BiancaIalangi Jul 1, 2024
0075097
fixed from_big_float conversion
BiancaIalangi Jul 2, 2024
5ae858a
fix clippy + cargo fmt
BiancaIalangi Jul 2, 2024
6cff650
precision test
mihaicalinluca Jul 2, 2024
d250ced
Merge pull request #1692 from multiversx/tests-managed_decimal-signed
BiancaIalangi Jul 2, 2024
58065be
ManagedDecimal log2 implementation
andrei-marinica Jun 28, 2024
030c22f
ManagedDecimal log2 optimization
andrei-marinica Jun 28, 2024
f8f7590
Merge pull request #1691 from multiversx/log2
andrei-marinica Jul 2, 2024
3b2b4c8
tests for log2
mihaicalinluca Jul 3, 2024
8eea61e
cleanup
andrei-marinica Jul 4, 2024
5a6a5e8
big_float_ln mandos split
andrei-marinica Jul 4, 2024
b4e1882
big float features ln refactor
andrei-marinica Jul 4, 2024
fa61b20
big float features ln test
andrei-marinica Jul 4, 2024
92fb23b
big float features ln mandos gas
andrei-marinica Jul 4, 2024
c1c68cd
pltter in own workspace
andrei-marinica Jul 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
517 changes: 17 additions & 500 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ members = [

"tools/mxpy-snippet-generator",
"tools/payload-macro-generator",
"tools/plotter",
# "tools/plotter",

"vm",

Expand Down
2 changes: 1 addition & 1 deletion contracts/feature-tests/abi-tester/src/abi_test_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub struct OnlyShowsUpInEsdtAttr {
pub field: OnlyShowsUpAsNested10,
}

#[derive(TypeAbi)]
#[type_abi]
pub struct ManagedDecimalWrapper<M: ManagedTypeApi> {
#[allow(dead_code)]
pub field: ManagedDecimal<M, ConstDecimals<2>>,
Expand Down
4 changes: 2 additions & 2 deletions contracts/feature-tests/basic-features/src/big_num_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ pub trait BigIntMethods {

#[endpoint]
fn log2_big_uint(&self, a: BigUint) -> u32 {
a.log2()
a.log2_floor().unwrap_or_default()
}

#[endpoint]
fn log2_big_uint_ref(&self, a: &BigUint) -> u32 {
a.log2()
a.log2_floor().unwrap_or_default()
}

#[endpoint]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"steps": [
{
"step": "setState",
"accounts": {
"sc:basic-features": {
"nonce": "0",
"balance": "0",
"code": "mxsc:../output/big-float-features.mxsc.json"
},
"address:an_account": {
"nonce": "0",
"balance": "100000000000"
}
}
},
{
"step": "scCall",
"id": "ln_big_float_precision_9(23)",
"comment": "ln(23) = 3.135514648 (9 decimals)",
"tx": {
"from": "address:an_account",
"to": "sc:basic-features",
"function": "ln_big_float_precision_9",
"arguments": [
"23"
],
"gasLimit": "2,000,000",
"gasPrice": "0"
},
"expect": {
"out": [
"+3135514648"
]
}
},
{
"step": "scCall",
"id": "ln_big_float_any_precision(23, 9)",
"comment": "ln(23) = 3.135514648 (9 decimals)",
"tx": {
"from": "address:an_account",
"to": "sc:basic-features",
"function": "ln_big_float_any_precision",
"arguments": [
"23",
"9"
],
"gasLimit": "2,000,000",
"gasPrice": "0"
},
"expect": {
"out": [
"u32:5|+3135514648|u32:9"
]
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -820,26 +820,6 @@
"-1"
]
}
},
{
"step": "scCall",
"id": "LnBigFloatRef - 1",
"tx": {
"from": "address:an_account",
"to": "sc:basic-features",
"function": "ln_big_float_ref_wrapped",
"arguments": [
"23",
"9"
],
"gasLimit": "50,000,000",
"gasPrice": "0"
},
"expect": {
"out": [
"0x00000004bae4281800000009"
]
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ multiversx_sc::imports!();
pub mod big_float_methods;
pub mod big_float_methods_wrapped;
pub mod big_float_operators;
pub mod big_float_operators_ln;
pub mod big_float_operators_wrapped;

#[multiversx_sc::contract]
pub trait BigFloatFeatures:
big_float_methods::BigFloatMethods
+ big_float_operators::BigFloatOperators
+ big_float_methods_wrapped::BigFloatWrappedMethods
+ big_float_operators_ln::BigFloatWrappedLn
+ big_float_operators_wrapped::BigFloatWrappedOperators
{
#[init]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,4 @@ pub trait BigFloatOperators {
r /= b;
r
}
#[endpoint]
fn ln_big_float_ref(&self, a: &BigFloat) -> BigFloat {
a.ln()
.unwrap_or_else(|| sc_panic!("log argument must pe strictly positive"))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
multiversx_sc::imports!();

#[multiversx_sc::module]
pub trait BigFloatWrappedLn {
#[endpoint]
fn ln_big_float_ref(&self, a: &BigFloat) -> BigFloat {
a.ln()
.unwrap_or_else(|| sc_panic!("log argument must pe strictly positive"))
}

#[endpoint]
fn ln_big_float_precision_9(
&self,
a: BigInt,
) -> ManagedDecimalSigned<Self::Api, ConstDecimals<9>> {
let number = self.ln_big_float_ref(&BigFloat::from(a));
number.to_managed_decimal_signed(ConstDecimals)
}

#[endpoint]
fn ln_big_float_any_precision(
&self,
a: BigInt,
precision: usize,
) -> ManagedDecimalSigned<Self::Api, usize> {
let number = self.ln_big_float_ref(&BigFloat::from(a));
number.to_managed_decimal_signed(precision)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,4 @@ pub trait BigFloatWrappedOperators: big_float_operators::BigFloatOperators {
let number = self.div_assign_big_float_ref(&BigFloat::from(a), &BigFloat::from(b));
number.to_fixed_point(&BigFloat::from(fixed_point_denominator))
}

#[endpoint]
fn ln_big_float_ref_wrapped(
&self,
a: BigInt,
precision: usize,
) -> ManagedDecimal<Self::Api, usize> {
let number = self.ln_big_float_ref(&BigFloat::from(a));
number.to_managed_decimal(precision)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ fn world() -> ScenarioWorld {
ScenarioWorld::vm_go()
}

#[test]
fn big_float_ln_go() {
world().run("scenarios/big_float_ln.scen.json");
}

#[test]
fn big_float_new_from_big_int_go() {
world().run("scenarios/big_float_new_from_big_int.scen.json");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ fn world() -> ScenarioWorld {
blockchain
}

#[test]
fn big_float_ln_rs() {
world().run("scenarios/big_float_ln.scen.json");
}

#[test]
fn big_float_new_from_big_int_rs() {
world().run("scenarios/big_float_new_from_big_int.scen.json");
Expand Down
9 changes: 5 additions & 4 deletions contracts/feature-tests/big-float-features/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
////////////////////////////////////////////////////

// Init: 1
// Endpoints: 72
// Endpoints: 73
// Async Callback (empty): 1
// Total number of exported functions: 74
// Total number of exported functions: 75

#![no_std]

Expand Down Expand Up @@ -54,7 +54,6 @@ multiversx_sc_wasm_adapter::endpoints! {
mul_assign_big_float_ref => mul_assign_big_float_ref
div_assign_big_float => div_assign_big_float
div_assign_big_float_ref => div_assign_big_float_ref
ln_big_float_ref => ln_big_float_ref
new_from_parts_big_float_wrapped => new_from_parts_big_float_wrapped
new_from_frac_big_float_wrapped => new_from_frac_big_float_wrapped
new_from_sci_big_float_wrapped => new_from_sci_big_float_wrapped
Expand All @@ -73,6 +72,9 @@ multiversx_sc_wasm_adapter::endpoints! {
pow_big_float_ref_wrapped => pow_big_float_ref_wrapped
big_float_zero_wrapped => big_float_zero_wrapped
big_float_neg_wrapped => big_float_neg_wrapped
ln_big_float_ref => ln_big_float_ref
ln_big_float_precision_9 => ln_big_float_precision_9
ln_big_float_any_precision => ln_big_float_any_precision
add_big_float_wrapped => add_big_float_wrapped
add_big_float_ref_wrapped => add_big_float_ref_wrapped
sub_big_float_wrapped => sub_big_float_wrapped
Expand All @@ -89,7 +91,6 @@ multiversx_sc_wasm_adapter::endpoints! {
mul_assign_big_float_ref_wrapped => mul_assign_big_float_ref_wrapped
div_assign_big_float_wrapped => div_assign_big_float_wrapped
div_assign_big_float_ref_wrapped => div_assign_big_float_ref_wrapped
ln_big_float_ref_wrapped => ln_big_float_ref_wrapped
)
}

Expand Down
2 changes: 1 addition & 1 deletion framework/base/src/api/managed_types/big_int_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub trait BigIntApiImpl: HandleTypeInfo + ErrorApi {

fn bi_sqrt(&self, dest: Self::BigIntHandle, x: Self::BigIntHandle);
fn bi_pow(&self, dest: Self::BigIntHandle, x: Self::BigIntHandle, y: Self::BigIntHandle);
fn bi_log2(&self, x: Self::BigIntHandle) -> u32;
fn bi_log2(&self, x: Self::BigIntHandle) -> i32;

fn bi_and(&self, dest: Self::BigIntHandle, x: Self::BigIntHandle, y: Self::BigIntHandle);
fn bi_or(&self, dest: Self::BigIntHandle, x: Self::BigIntHandle, y: Self::BigIntHandle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl BigIntApiImpl for super::UncallableApi {
unreachable!()
}

fn bi_log2(&self, _x: Self::BigIntHandle) -> u32 {
fn bi_log2(&self, _x: Self::BigIntHandle) -> i32 {
unreachable!()
}

Expand Down
1 change: 1 addition & 0 deletions framework/base/src/err_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub const VALUE_EXCEEDS_SLICE: &str = "value exceeds target slice";
pub const CAST_TO_I64_ERROR: &str = "cast to i64 error";
pub const BIG_UINT_EXCEEDS_SLICE: &str = "big uint as_bytes exceed target slice";
pub const BIG_UINT_SUB_NEGATIVE: &str = "cannot subtract because result would be negative";
pub const UNSIGNED_NEGATIVE: &str = "cannot convert to unsigned, number is negative";

pub const DESERIALIZATION_INVALID_BYTE: &str = "call data deserialization error: not a valid byte";
pub const DESERIALIZATION_NOT_32_BYTES: &str =
Expand Down
1 change: 1 addition & 0 deletions framework/base/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod heap;
mod interaction;
mod io;
mod managed;
pub(crate) mod math_util;
mod static_buffer;

pub use crypto::*;
Expand Down
55 changes: 43 additions & 12 deletions framework/base/src/types/managed/basic/big_float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use crate::{
api::{
use_raw_handle, BigFloatApiImpl, ManagedTypeApi, ManagedTypeApiImpl, Sign, StaticVarApiImpl,
},
types::{BigInt, BigUint, Decimals, ManagedDecimal, ManagedType},
contract_base::ErrorHelper,
types::{BigInt, BigUint, Decimals, ManagedDecimalSigned, ManagedType},
};
use alloc::string::String;

Expand Down Expand Up @@ -175,8 +176,11 @@ impl<M: ManagedTypeApi> BigFloat<M> {
(self * denominator).trunc()
}

pub fn to_managed_decimal<T: Decimals>(&self, decimals: T) -> ManagedDecimal<M, T> {
ManagedDecimal::<M, T>::from_big_float(self, decimals)
pub fn to_managed_decimal_signed<T: Decimals>(
&self,
decimals: T,
) -> ManagedDecimalSigned<M, T> {
ManagedDecimalSigned::<M, T>::from_big_float(self, decimals)
}

/// Computes the natural logarithm of the current number.
Expand Down Expand Up @@ -223,13 +227,14 @@ impl<M: ManagedTypeApi> BigFloat<M> {
let trunc_val_unsigned = trunc_val
.into_big_uint()
.unwrap_or_sc_panic("log argument must be positive");
let bit_log2 = trunc_val_unsigned.log2(); // approximate, based on position of the most significant bit
if bit_log2 == u32::MAX {
// means the input was zero, TODO: change log2 return type

// start with aproximation, based on position of the most significant bit
let Some(log2_floor) = trunc_val_unsigned.log2_floor() else {
// means the input was zero, practically unreachable
return BigFloat::from(0i64);
// return None;
}
let divisor = BigFloat::from(1 << bit_log2);
};

let divisor = BigFloat::from(1 << log2_floor);
let x = self / &divisor; // normalize to [1.0, 2.0]

debug_assert!(x >= 1);
Expand All @@ -238,13 +243,11 @@ impl<M: ManagedTypeApi> BigFloat<M> {
let mut result = x.ln_between_one_and_two();

let ln_of_2 = BigFloat::from_frac(693147180, DENOMINATOR); // 0.69314718
result += BigFloat::from(bit_log2 as i32) * ln_of_2;
result += BigFloat::from(log2_floor as i32) * ln_of_2;

result
}
}

impl<M: ManagedTypeApi> BigFloat<M> {
#[inline]
pub fn zero() -> Self {
BigFloat::from_handle(M::managed_type_impl().bf_new_zero())
Expand Down Expand Up @@ -304,6 +307,34 @@ impl<M: ManagedTypeApi> BigFloat<M> {
}
}

impl<M: ManagedTypeApi> From<f64> for BigFloat<M> {
fn from(x: f64) -> Self {
const PREC: i64 = 1_000_000_000;
Self::from_frac((x * PREC as f64) as i64, PREC)
}
}

impl<M: ManagedTypeApi> From<f32> for BigFloat<M> {
fn from(x: f32) -> Self {
Self::from(x as f64)
}
}

impl<M: ManagedTypeApi> BigFloat<M> {
/// Warning: cannot be used in contracts. It is only meant to simplify certain tests.
///
/// It might also not be optimal with respect to precision.
pub fn to_f64(&self) -> f64 {
const PREC: i64 = 1_000_000_000;
let mut rescaled = Self::from(PREC);
rescaled *= self;
let ln_units = rescaled.trunc().to_i64().unwrap_or_else(|| {
ErrorHelper::<M>::signal_error_with_message("BigFloat out of precision range")
});
ln_units as f64 / PREC as f64
}
}

impl<M: ManagedTypeApi> Clone for BigFloat<M> {
fn clone(&self) -> Self {
let new_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle());
Expand Down
Loading
Loading