diff --git a/framework/base/src/types/managed/wrapped/managed_decimal.rs b/framework/base/src/types/managed/wrapped/managed_decimal.rs index 89a7c47ca9..6e06bb3cfa 100644 --- a/framework/base/src/types/managed/wrapped/managed_decimal.rs +++ b/framework/base/src/types/managed/wrapped/managed_decimal.rs @@ -142,6 +142,45 @@ impl ManagedDecimal { num_decimals, ) } + + // pub fn log(self, target_base: f64, precision: T) -> ManagedDecimal { + // let num_decimals = f64::from(precision.num_decimals() as u32); + // let number = f64::from(self.data.to_u64().unwrap() as u32); + + // assert!(number >= 1f64 && target_base >= 1f64, "wrong input"); + + // let precise = (number.log10() * num_decimals / target_base.log10()) + // .trunc() + // .round() as u64; + + // ManagedDecimal::from_raw_units(BigUint::::from(precise), precision) + // } + + pub fn ln(self, decimals: D) -> ManagedDecimal { + // find the highest power of 2 less than or equal to self + let log2 = self.data.log2(); // most significant bit + let divisor = 1 << log2; + let x = self.to_big_float() / BigFloat::from(divisor); // normalize to [1.0, 2.0] + + let ln_of_2 = BigFloat::from_frac(69314718i64, 1_000_000_000i64); + 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, 1_000_000_000i64); // 0.44717955, 9 decimals + let fifth = BigFloat::from_frac(56570851i64, 1_000_000_000i64); // 0.056570851, 9 decimals + + // approximating polynom for getting 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; + let final_result = result + add_member; + + final_result.to_managed_decimal(decimals.num_decimals()) + } + + pub fn nth_root(self, _root: ManagedDecimal, _precision: D) -> ManagedDecimal { + todo!() + } } impl ManagedDecimal> { @@ -339,6 +378,24 @@ where } } +impl Add> for ManagedDecimal { + type Output = Self; + + fn add(self, other: ManagedDecimal) -> Self::Output { + let scaled = other.rescale(self.scale()); + ManagedDecimal::from_raw_units(&self.data + &scaled.data, scaled.decimals) + } +} + +impl Sub> for ManagedDecimal { + type Output = Self; + + fn sub(self, other: ManagedDecimal) -> Self::Output { + let scaled = other.rescale(self.scale()); + ManagedDecimal::from_raw_units(&self.data - &scaled.data, scaled.decimals) + } +} + impl PartialEq> for ManagedDecimal { diff --git a/framework/scenario/tests/managed_decimal_test.rs b/framework/scenario/tests/managed_decimal_test.rs index cbe701c9cf..fa4d10fcba 100644 --- a/framework/scenario/tests/managed_decimal_test.rs +++ b/framework/scenario/tests/managed_decimal_test.rs @@ -124,3 +124,87 @@ fn test_encode_decode() { check_top_encode_decode(fixed_const, bytes); } + +#[test] +fn test_managed_decimal_ln() { + let fixed = + ManagedDecimal::::from_raw_units(BigUint::from(23u64), 0usize); + + let ln_fixed = fixed.ln(10usize); // precision of 10 decimal points + + println!("{ln_fixed:?}"); + assert_eq!( + ln_fixed, + ManagedDecimal::::from_raw_units( + BigUint::from(313549421u64), + 10usize + ) + ); +} + +// #[test] +// fn test_managed_decimal_nth_root() { +// let fixed = +// ManagedDecimal::::from_raw_units(BigUint::from(567u64), 1usize); + +// let fifth_root = fixed.clone().root(5f64, 100usize); +// let fifth_root_higher_prec = fixed.root(5f64, 100_000usize); + +// assert_eq!( +// fifth_root, +// ManagedDecimal::::from_raw_units(BigUint::from(355u64), 100usize) +// ); +// assert_eq!( +// fifth_root_higher_prec, +// ManagedDecimal::::from_raw_units( +// BigUint::from(355399u64), +// 100_000usize +// ) +// ); + +// let const_fixed: ManagedDecimal> = +// ManagedDecimal::>::const_decimals_from_raw(BigUint::from( +// 876u64, +// )); + +// let seventh_root_var = const_fixed.clone().root(7f64, 10_000usize); +// let seventh_root_const = const_fixed.root(7f64, ConstDecimals::<10_000>); + +// assert_eq!( +// seventh_root_var, +// ManagedDecimal::::from_raw_units( +// BigUint::from(26324u64), +// 10_000usize +// ) +// ); +// assert_eq!( +// seventh_root_const, +// ManagedDecimal::>::const_decimals_from_raw( +// BigUint::from(26324u64) +// ) +// ); +// } + +// #[test] +// fn test_managed_decimal_log_any_base() { +// let fixed = ManagedDecimal::from_raw_units(BigUint::from(10u64), 1usize); +// let log2_fixed = fixed.log(BigUint::from(2u64), 10_000usize); +// assert_eq!( +// log2_fixed, +// ManagedDecimal::::from_raw_units( +// BigUint::from(33219u64), +// 10_000usize +// ) +// ); + +// let fixed_const = ManagedDecimal::>::const_decimals_from_raw( +// BigUint::from(10u64), +// ); +// let log2_const = fixed_const.log(BigUint::from(2u64), ConstDecimals::<10_000>); +// assert_eq!( +// log2_const, +// ManagedDecimal::>::const_decimals_from_raw( +// BigUint::from(33219u64) +// ) +// ); +// }