use core::ops::{Mul, MulAssign};
use oxinum_core::Sign;
use super::float::{BigFloat, RoundingMode};
use super::nonfinite::{nonfinite_propagate, BinOp};
impl BigFloat {
pub fn mul_ref(&self, other: &BigFloat) -> BigFloat {
self.mul_ref_with_mode(other, RoundingMode::HalfEven)
}
pub fn mul_ref_with_mode(&self, other: &BigFloat, mode: RoundingMode) -> BigFloat {
if let Some(result) = nonfinite_propagate(self, other, BinOp::Mul) {
return result;
}
let target_prec = self.precision.max(other.precision);
if self.is_zero() || other.is_zero() {
return BigFloat::zero(target_prec);
}
let out_sign = if self.sign == other.sign {
Sign::Positive
} else {
Sign::Negative
};
let out_mantissa = &self.mantissa * &other.mantissa;
let out_exponent = self.exponent.saturating_add(other.exponent);
BigFloat::from_parts(out_sign, out_mantissa, out_exponent, target_prec, mode)
}
}
impl Mul<&BigFloat> for &BigFloat {
type Output = BigFloat;
#[inline]
fn mul(self, rhs: &BigFloat) -> BigFloat {
self.mul_ref(rhs)
}
}
impl Mul<BigFloat> for BigFloat {
type Output = BigFloat;
#[inline]
fn mul(self, rhs: BigFloat) -> BigFloat {
self.mul_ref(&rhs)
}
}
impl Mul<&BigFloat> for BigFloat {
type Output = BigFloat;
#[inline]
fn mul(self, rhs: &BigFloat) -> BigFloat {
self.mul_ref(rhs)
}
}
impl Mul<BigFloat> for &BigFloat {
type Output = BigFloat;
#[inline]
fn mul(self, rhs: BigFloat) -> BigFloat {
self.mul_ref(&rhs)
}
}
impl MulAssign<&BigFloat> for BigFloat {
#[inline]
fn mul_assign(&mut self, rhs: &BigFloat) {
*self = self.mul_ref(rhs);
}
}
impl MulAssign<BigFloat> for BigFloat {
#[inline]
fn mul_assign(&mut self, rhs: BigFloat) {
*self = self.mul_ref(&rhs);
}
}