use std::cmp::Ordering;
use num_traits::{Num, One, Signed, Zero};
use super::constants;
use super::float::{BigFloat, RoundingMode};
const DEFAULT_PREC: u32 = 53;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseBigFloatError(String);
impl std::fmt::Display for ParseBigFloatError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ParseBigFloatError: {}", self.0)
}
}
impl std::error::Error for ParseBigFloatError {}
impl Zero for BigFloat {
#[inline]
fn zero() -> Self {
BigFloat::zero(DEFAULT_PREC)
}
#[inline]
fn is_zero(&self) -> bool {
BigFloat::is_zero(self)
}
}
impl One for BigFloat {
#[inline]
fn one() -> Self {
BigFloat::from_i64(1, DEFAULT_PREC, RoundingMode::HalfEven)
}
}
impl Num for BigFloat {
type FromStrRadixErr = ParseBigFloatError;
fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
if radix != 10 {
return Err(ParseBigFloatError(format!(
"BigFloat::from_str_radix only supports radix 10, got {radix}"
)));
}
let f: f64 = s
.parse()
.map_err(|e: std::num::ParseFloatError| ParseBigFloatError(e.to_string()))?;
BigFloat::from_f64(f, DEFAULT_PREC).map_err(|e| ParseBigFloatError(e.to_string()))
}
}
impl Signed for BigFloat {
#[inline]
fn abs(&self) -> Self {
BigFloat::abs(self)
}
fn abs_sub(&self, other: &Self) -> Self {
if self > other {
self.clone() - other.clone()
} else {
BigFloat::zero(DEFAULT_PREC)
}
}
fn signum(&self) -> Self {
let s = BigFloat::signum(self);
BigFloat::from_i64(s as i64, DEFAULT_PREC, RoundingMode::HalfEven)
}
fn is_positive(&self) -> bool {
BigFloat::signum(self) > 0
}
fn is_negative(&self) -> bool {
BigFloat::signum(self) < 0
}
}
impl num_traits::float::FloatConst for BigFloat {
fn PI() -> Self {
constants::pi(DEFAULT_PREC).expect("FloatConst PI: generation at 53 bits is infallible")
}
fn E() -> Self {
constants::e_const(DEFAULT_PREC).expect("FloatConst E: generation at 53 bits is infallible")
}
fn LN_2() -> Self {
constants::ln2(DEFAULT_PREC).expect("FloatConst LN_2: generation at 53 bits is infallible")
}
fn LN_10() -> Self {
let ten = BigFloat::from_i64(10, DEFAULT_PREC, RoundingMode::HalfEven);
ten.ln(DEFAULT_PREC, RoundingMode::HalfEven)
.expect("FloatConst LN_10: ln(10) at 53 bits is infallible")
}
fn LOG2_E() -> Self {
let one = BigFloat::from_i64(1, DEFAULT_PREC, RoundingMode::HalfEven);
let ln2 = constants::ln2(DEFAULT_PREC)
.expect("FloatConst LOG2_E: ln2 generation at 53 bits is infallible");
one.div_ref(&ln2)
.expect("FloatConst LOG2_E: 1/ln2 is infallible (ln2 is nonzero)")
}
fn LOG10_E() -> Self {
let one = BigFloat::from_i64(1, DEFAULT_PREC, RoundingMode::HalfEven);
let ln10 = Self::LN_10();
one.div_ref(&ln10)
.expect("FloatConst LOG10_E: 1/ln10 is infallible (ln10 is nonzero)")
}
fn SQRT_2() -> Self {
BigFloat::from_i64(2, DEFAULT_PREC, RoundingMode::HalfEven)
.sqrt(DEFAULT_PREC, RoundingMode::HalfEven)
.expect("FloatConst SQRT_2: sqrt(2) at 53 bits is infallible")
}
fn FRAC_1_SQRT_2() -> Self {
let one = BigFloat::from_i64(1, DEFAULT_PREC, RoundingMode::HalfEven);
one.div_ref(&Self::SQRT_2())
.expect("FloatConst FRAC_1_SQRT_2: 1/sqrt(2) is infallible")
}
fn FRAC_1_PI() -> Self {
let one = BigFloat::from_i64(1, DEFAULT_PREC, RoundingMode::HalfEven);
one.div_ref(&Self::PI())
.expect("FloatConst FRAC_1_PI: 1/pi is infallible")
}
fn FRAC_2_PI() -> Self {
let two = BigFloat::from_i64(2, DEFAULT_PREC, RoundingMode::HalfEven);
two.div_ref(&Self::PI())
.expect("FloatConst FRAC_2_PI: 2/pi is infallible")
}
fn FRAC_2_SQRT_PI() -> Self {
let pi = Self::PI();
let sqrt_pi = pi
.sqrt(DEFAULT_PREC, RoundingMode::HalfEven)
.expect("FloatConst FRAC_2_SQRT_PI: sqrt(pi) is infallible");
let two = BigFloat::from_i64(2, DEFAULT_PREC, RoundingMode::HalfEven);
two.div_ref(&sqrt_pi)
.expect("FloatConst FRAC_2_SQRT_PI: 2/sqrt(pi) is infallible")
}
fn FRAC_PI_2() -> Self {
let two = BigFloat::from_i64(2, DEFAULT_PREC, RoundingMode::HalfEven);
Self::PI()
.div_ref(&two)
.expect("FloatConst FRAC_PI_2: pi/2 is infallible")
}
fn FRAC_PI_3() -> Self {
let three = BigFloat::from_i64(3, DEFAULT_PREC, RoundingMode::HalfEven);
Self::PI()
.div_ref(&three)
.expect("FloatConst FRAC_PI_3: pi/3 is infallible")
}
fn FRAC_PI_4() -> Self {
let four = BigFloat::from_i64(4, DEFAULT_PREC, RoundingMode::HalfEven);
Self::PI()
.div_ref(&four)
.expect("FloatConst FRAC_PI_4: pi/4 is infallible")
}
fn FRAC_PI_6() -> Self {
let six = BigFloat::from_i64(6, DEFAULT_PREC, RoundingMode::HalfEven);
Self::PI()
.div_ref(&six)
.expect("FloatConst FRAC_PI_6: pi/6 is infallible")
}
fn FRAC_PI_8() -> Self {
let eight = BigFloat::from_i64(8, DEFAULT_PREC, RoundingMode::HalfEven);
Self::PI()
.div_ref(&eight)
.expect("FloatConst FRAC_PI_8: pi/8 is infallible")
}
}
impl num_traits::float::TotalOrder for BigFloat {
#[inline]
fn total_cmp(&self, other: &Self) -> Ordering {
BigFloat::total_cmp(self, other)
}
}