Skip to content

Commit

Permalink
BigFloat - ln fix
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-marinica committed Jun 12, 2024
1 parent fada5b3 commit 20acd9e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,13 @@ fn big_float_overflow_test_rs() {

#[test]
fn big_float_ln_test_rs() {
let fixed = BigFloat::<StaticApi>::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)
);
let x = BigFloat::<StaticApi>::from(23i64);
let ln_x = x.ln();
assert_eq!(ln_x.to_managed_decimal(9usize).to_string(), "3.135514648");
assert!(ln_x.is_close(
&BigFloat::from_frac(3135514648, 1_000_000_000), // 3.135514648
&BigFloat::from_frac(1, 1_000_000_000)
));
}

#[test]
Expand Down
38 changes: 22 additions & 16 deletions framework/base/src/types/managed/basic/big_float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,23 +93,27 @@ big_float_conv_num! {i16}
big_float_conv_num! {i8}

impl<M: ManagedTypeApi> BigFloat<M> {
#[inline]
pub fn neg(&self) -> Self {
let new_bf_handle: M::BigFloatHandle =
use_raw_handle(M::static_var_api_impl().next_handle());
M::managed_type_impl().bf_neg(new_bf_handle.clone(), self.handle.clone());
BigFloat::from_handle(new_bf_handle)
}

#[inline]
pub fn abs(&self) -> Self {
let new_bf_handle: M::BigFloatHandle =
use_raw_handle(M::static_var_api_impl().next_handle());
M::managed_type_impl().bf_abs(new_bf_handle.clone(), self.handle.clone());
BigFloat::from_handle(new_bf_handle)
}

pub fn from_big_uint(big_uint: &BigUint<M>) -> Self {
let new_bf_handle: M::BigFloatHandle =
use_raw_handle(M::static_var_api_impl().next_handle());
M::managed_type_impl().bf_set_bi(new_bf_handle.clone(), big_uint.handle.clone());
BigFloat::from_handle(new_bf_handle)
}

#[inline]
pub fn from_big_int(big_int: &BigInt<M>) -> Self {
let new_bf_handle: M::BigFloatHandle =
use_raw_handle(M::static_var_api_impl().next_handle());
Expand Down Expand Up @@ -169,31 +173,33 @@ impl<M: ManagedTypeApi> BigFloat<M> {
}

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

pub fn ln(&self, precision: BigUint<M>) -> Self {
pub fn ln(&self) -> Self {
// find the highest power of 2 less than or equal to self
let mng_dec = self
.to_fixed_point(&BigFloat::from(precision))
let trunc_val = self.trunc();
let trunc_val_unsigned = trunc_val
.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);
.unwrap_or_sc_panic("log argument must be positive");
let bit_log2 = trunc_val_unsigned.log2(); // aproximate, based on position of the most significant bit
let divisor = BigFloat::from(1 << bit_log2);
let x = self / &divisor; // normalize to [1.0, 2.0]

debug_assert!(x >= 1);
debug_assert!(x <= 2);

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 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 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
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;
(((fourth + fifth * x.clone()) * x.clone() + third) * x.clone() + second) * x + first;
let add_member = BigFloat::from_big_uint(&BigUint::from(bit_log2)) * ln_of_2;
result + add_member
}
}
Expand Down
7 changes: 7 additions & 0 deletions framework/base/src/types/managed/basic/big_float_cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ use crate::api::{use_raw_handle, BigFloatApiImpl, ManagedTypeApi, StaticVarApiIm

use super::{BigFloat, BigInt};

impl<M: ManagedTypeApi> BigFloat<M> {
pub fn is_close(&self, other: &Self, abs_tolerance: &Self) -> bool {
// TODO: temp handles
&(self - other).abs() <= abs_tolerance
}
}

impl<M: ManagedTypeApi> PartialEq for BigFloat<M> {
#[inline]
fn eq(&self, other: &Self) -> bool {
Expand Down

0 comments on commit 20acd9e

Please sign in to comment.