multiversx_sc/types/managed/wrapped/managed_decimal/
managed_decimal_logarithm.rs1use super::decimals::{Decimals, LnDecimals};
2use super::ManagedDecimalSigned;
3use super::{ManagedDecimal, NumDecimals};
4
5use crate::types::ManagedRef;
6use crate::{
7 api::ManagedTypeApi,
8 contract_base::ErrorHelper,
9 types::{BigInt, BigUint, Sign},
10};
11
12fn compute_ln<M: ManagedTypeApi>(
13 data: &BigUint<M>,
14 num_decimals: NumDecimals,
15) -> Option<ManagedDecimalSigned<M, LnDecimals>> {
16 let Some(log2_floor) = data.log2_floor() else {
18 return None;
20 };
21
22 let scaling_factor_9 = LnDecimals::new().scaling_factor();
23 let divisor = BigUint::from(1u64) << log2_floor as usize;
24 let normalized = data * &*scaling_factor_9 / divisor;
25
26 let x = normalized
27 .to_u64()
28 .unwrap_or_else(|| ErrorHelper::<M>::signal_error_with_message("ln internal error"))
29 as i64;
30
31 let mut result = crate::types::math_util::logarithm_i64::ln_polynomial(x);
32 crate::types::math_util::logarithm_i64::ln_add_bit_log2(&mut result, log2_floor);
33
34 debug_assert!(result > 0);
35
36 crate::types::math_util::logarithm_i64::ln_sub_decimals(&mut result, num_decimals);
37
38 Some(ManagedDecimalSigned::from_raw_units(
39 BigInt::from(result),
40 LnDecimals::new(),
41 ))
42}
43
44fn compute_log2<M: ManagedTypeApi>(
45 data: &BigUint<M>,
46 num_decimals: NumDecimals,
47) -> Option<ManagedDecimalSigned<M, LnDecimals>> {
48 let Some(log2_floor) = data.log2_floor() else {
50 return None;
52 };
53
54 let scaling_factor_9 = LnDecimals::new().scaling_factor();
55 let divisor = BigUint::from(1u64) << log2_floor as usize;
56 let normalized = data * &*scaling_factor_9 / divisor;
57
58 let x = normalized
59 .to_u64()
60 .unwrap_or_else(|| ErrorHelper::<M>::signal_error_with_message("log2 internal error"))
61 as i64;
62
63 let mut result = crate::types::math_util::logarithm_i64::log2_polynomial(x);
64 crate::types::math_util::logarithm_i64::log2_add_bit_log2(&mut result, log2_floor);
65
66 debug_assert!(result > 0);
67
68 crate::types::math_util::logarithm_i64::log2_sub_decimals(&mut result, num_decimals);
69
70 Some(ManagedDecimalSigned::from_raw_units(
71 BigInt::from(result),
72 LnDecimals::new(),
73 ))
74}
75
76impl<M: ManagedTypeApi, D: Decimals> ManagedDecimal<M, D> {
77 pub fn ln(&self) -> Option<ManagedDecimalSigned<M, LnDecimals>> {
83 compute_ln(&self.data, self.decimals.num_decimals())
84 }
85
86 pub fn log2(&self) -> Option<ManagedDecimalSigned<M, LnDecimals>> {
92 compute_log2(&self.data, self.decimals.num_decimals())
93 }
94}
95
96impl<M: ManagedTypeApi, D: Decimals> ManagedDecimalSigned<M, D> {
97 pub fn ln(&self) -> Option<ManagedDecimalSigned<M, LnDecimals>> {
103 if self.sign() != Sign::Plus {
104 return None;
105 }
106
107 let bu = unsafe { ManagedRef::wrap_handle(self.data.handle.clone()) };
108 compute_ln(&bu, self.decimals.num_decimals())
109 }
110
111 pub fn log2(&self) -> Option<ManagedDecimalSigned<M, LnDecimals>> {
117 if self.sign() != Sign::Plus {
118 return None;
119 }
120
121 let bu = unsafe { ManagedRef::wrap_handle(self.data.handle.clone()) };
122 compute_log2(&bu, self.decimals.num_decimals())
123 }
124}