diff --git a/contracts/feature-tests/big-float-features/tests/big_float_scenario_rs_test.rs b/contracts/feature-tests/big-float-features/tests/big_float_scenario_rs_test.rs index 66ca09ab86..9aa3dc14dd 100644 --- a/contracts/feature-tests/big-float-features/tests/big_float_scenario_rs_test.rs +++ b/contracts/feature-tests/big-float-features/tests/big_float_scenario_rs_test.rs @@ -56,6 +56,19 @@ fn big_float_overflow_test_rs() { assert_eq!(forth, &BigUint::from(2184473079534488064u64)); } +#[test] +fn big_float_ln_test_rs() { + let fixed = BigFloat::::from_frac(23i64, 2i64); + + let ln_fixed = fixed.ln(BigUint::from(10u64)); // precision of 10 decimal points + + println!("{ln_fixed:?}"); + assert_eq!( + ln_fixed, + BigFloat::from_frac(31355146488i64, 10_000_000_000i64) + ); +} + #[test] fn big_float_new_from_big_int_rs() { world().run("scenarios/big_float_new_from_big_int.scen.json"); diff --git a/framework/base/src/types/managed/basic/big_float.rs b/framework/base/src/types/managed/basic/big_float.rs index 934bd2c636..64c4515d4e 100644 --- a/framework/base/src/types/managed/basic/big_float.rs +++ b/framework/base/src/types/managed/basic/big_float.rs @@ -168,8 +168,33 @@ impl BigFloat { (self * denominator).trunc() } - pub fn to_managed_decimal(self, decimals: T) -> ManagedDecimal { - ManagedDecimal::::from_big_float(self, decimals) + pub fn to_managed_decimal(&self, decimals: T) -> ManagedDecimal { + ManagedDecimal::::from_big_float(&self, decimals) + } + + pub fn ln(&self, precision: BigUint) -> Self { + // find the highest power of 2 less than or equal to self + let mng_dec = self + .to_fixed_point(&BigFloat::from(precision)) + .into_big_uint() + .unwrap_or_sc_panic("can't calculate ln for this number"); + + let log2 = mng_dec.log2(); // most significant bit + let divisor = BigFloat::from(1 << log2); + let x = self / &divisor; // normalize to [1.0, 2.0] + + let ln_of_2 = BigFloat::from_frac(69314718i64, 100_000_000i64); // 0.69314718 8 decimals + let first = BigFloat::from_frac(17417939i64, 10_000_000i64); // 1.7417939, 7 decimals + let second = BigFloat::from_frac(28212026i64, 10_000_000i64); // 2.8212026, 7 decimals + let third = BigFloat::from_frac(14699568i64, 10_000_000i64); // 1.4699568, 7 decimals + let fourth = BigFloat::from_frac(44717955i64, 100_000_000i64); // 0.44717955, 8 decimals + let fifth = BigFloat::from_frac(56570851i64, 1_000_000_000i64); // 0.056570851, 9 decimals + + // approximating polynom to get the result + let result = + (((fourth - fifth * x.clone()) * x.clone() - third) * x.clone() + second) * x - first; + let add_member = BigFloat::from_big_uint(&BigUint::from(log2)) * ln_of_2; + result + add_member } } diff --git a/framework/base/src/types/managed/wrapped/managed_decimal.rs b/framework/base/src/types/managed/wrapped/managed_decimal.rs index 89a7c47ca9..fb31e80e58 100644 --- a/framework/base/src/types/managed/wrapped/managed_decimal.rs +++ b/framework/base/src/types/managed/wrapped/managed_decimal.rs @@ -126,7 +126,7 @@ impl ManagedDecimal { } pub fn from_big_float( - big_float: BigFloat, + big_float: &BigFloat, num_decimals: T, ) -> ManagedDecimal { let scaling_factor: &BigUint = &num_decimals.scaling_factor(); diff --git a/framework/scenario/tests/managed_decimal_test.rs b/framework/scenario/tests/managed_decimal_test.rs index cbe701c9cf..ea862953e7 100644 --- a/framework/scenario/tests/managed_decimal_test.rs +++ b/framework/scenario/tests/managed_decimal_test.rs @@ -64,10 +64,10 @@ pub fn test_managed_decimal() { let float_1 = BigFloat::::from_frac(3i64, 2i64); let fixed_float_1 = ManagedDecimal::>::from_big_float( - float_1.clone(), + &float_1, ConstDecimals::<1>, ); - let fixed_float_2 = ManagedDecimal::::from_big_float(float_1, 1usize); + let fixed_float_2 = ManagedDecimal::::from_big_float(&float_1, 1usize); assert_eq!( fixed_float_1,