pub use crate::bigint::float_para::{RoundingMode, Accuracy};
use crate::bigint::bigint::BISign;
use crate::bigint::{Nat, BigInt, Rat};
use crate::bigint::float_para::Form;
use crate::bigint::float_para::RoundingMode::{*};
use crate::bigint::bigint::BISign::{Negative, Natural};
use crate::bigint::arith::{add_vw_inner, shr_vu_inner};
use crate::bigint::arith_generic::shl_vu_inner;
use crate::bigint::util;
use std::ops::{Neg, Div, DivAssign, Add, AddAssign, Sub, SubAssign, Mul, MulAssign};
use std::cmp::Ordering;
#[derive(Clone)]
pub struct Float {
pub(super) mode: RoundingMode,
pub(super) acc: Accuracy,
pub(super) form: Form,
pub(super) neg: BISign,
pub(super) prec: usize,
pub(super) exp: isize,
pub(super) mant: Nat,
}
impl Float {
pub fn deep_clone(&self) -> Float {
Float {
mode: self.mode,
acc: self.acc,
form: self.form,
neg: self.neg,
prec: self.prec,
exp: self.exp,
mant: self.mant.deep_clone(),
}
}
pub fn is_nan(&self) -> bool {
self.form.is_nan()
}
pub const fn max_exp() -> isize {
std::i32::MAX as isize
}
pub const fn min_exp() -> isize {
std::i32::MIN as isize
}
pub const fn max_precision() -> usize {
std::u32::MAX as usize
}
pub fn set_precision(&mut self, prec: usize) {
self.acc = Accuracy::Exact;
if prec == 0 {
self.prec = 0;
if self.form.is_finite() {
self.acc = Self::make_accuracy(self.neg == Negative);
self.form = Form::Zero;
}
return;
}
let prec = std::cmp::min(Self::max_precision(), prec);
let old = self.prec;
self.prec = prec;
if self.prec < old {
self.round(0)
}
}
pub fn set_mode(&mut self, mode: RoundingMode) {
self.mode = mode;
self.acc = Accuracy::Exact;
}
pub fn get_precision(&self) -> usize {
self.prec
}
pub fn required_min_precision(&self) -> usize {
if !self.form.is_finite() {
0
} else {
(self.mant.as_vec().len() << 5) - self.mant.trailling_zeros()
}
}
pub fn get_mode(&self) -> RoundingMode {
self.mode
}
pub fn get_accuracy(&self) -> Accuracy {
self.acc
}
pub fn signnum(&self) -> Option<isize> {
if self.is_nan() {
None
} else {
Some(
if self.form.is_zero() {
0
} else if self.neg == Negative {
-1
} else {
1
}
)
}
}
pub fn get_inf(is_negative: bool) -> Float {
let mut z = Self::default();
z.form = Form::Inf;
z.neg = BISign::from(is_negative);
z
}
pub fn mant_exp(&self) -> (Float, isize) {
let exp = if self.form.is_finite() {
self.exp
} else {
0
};
let mut mant = self.deep_clone();
if mant.form.is_finite() {
mant.exp = 0;
}
(mant, exp)
}
fn set_exp_and_round(&mut self, exp: isize, sbit: usize) {
if exp < Self::min_exp() {
self.acc = Self::make_accuracy(self.neg == Negative);
self.form = Form::Zero;
} else if exp > Self::max_exp() {
self.acc = Self::make_accuracy(self.neg != Negative);
self.form = Form::Inf;
} else {
self.form = Form::Finite;
self.exp = exp;
self.round(sbit);
}
}
pub fn set_mant_exp(&mut self, mant: Float, exp: isize) {
self.mode = mant.mode;
self.acc = mant.acc;
self.form = mant.form;
self.neg = mant.neg;
self.prec = mant.prec;
self.exp = mant.exp;
self.mant.clear();
self.mant.as_mut_vec().extend(mant.mant.iter());
if self.form.is_finite() {
self.set_exp_and_round(self.exp.saturating_add(exp), 0);
}
}
pub fn is_negative(&self) -> Option<bool> {
if self.is_nan() {
None
} else {
Some(self.neg == Negative)
}
}
pub fn is_infinite(&self) -> Option<bool> {
if self.is_nan() {
None
} else {
Some(self.form.is_infinite())
}
}
pub fn is_integer(&self) -> Option<bool> {
if self.is_nan() {
None
} else if !self.form.is_finite() {
Some(self.form.is_zero())
} else if self.exp <= 0 {
Some(false)
} else {
Some(self.prec <= (self.exp as usize) || self.required_min_precision() <= (self.exp as usize))
}
}
fn set_bits(&mut self, is_neg: bool, x: u64) {
if self.prec == 0 {
self.prec = 64;
}
self.acc = Accuracy::Exact;
self.neg = BISign::from(is_neg);
if x == 0 {
self.form = Form::Zero;
} else {
self.form = Form::Finite;
let s = x.leading_zeros();
self.mant.clear();
let tmp = x << s;
self.mant.as_mut_vec().push((tmp & 0xffffffff) as u32);
self.mant.as_mut_vec().push((tmp >> 32) as u32);
self.exp = (64 - s) as isize;
if self.prec < 64 {
self.round(0);
}
}
}
fn set_u64(&mut self, x: u64) {
self.set_bits(false, x);
}
fn set_i64(&mut self, x: i64) {
self.set_bits(x < 0, x.abs() as u64)
}
fn set_f64(&mut self, x: f64) {
if x.is_nan() {
self.form = Form::Nan;
} else {
if self.prec == 0 {
self.prec = 53;
}
self.acc = Accuracy::Exact;
self.neg = BISign::from(x.is_sign_negative());
if x == 0f64 {
self.form = Form::Zero;
} else if x.is_infinite() {
self.form = Form::Inf;
} else {
self.form = Form::Finite;
let (fmant, exp) = util::frexp(x);
let tmp = (1u64 << 63) | (fmant.to_bits() << 11);
self.mant.clear();
self.mant.as_mut_vec().push((tmp & 0xffffffff) as u32);
self.mant.as_mut_vec().push((tmp >> 32) as u32);
self.exp = exp;
if self.prec < 53 {
self.round(0);
}
}
}
}
fn set_float(&mut self, x: &Float) {
self.acc = Accuracy::Exact;
self.form = x.form;
self.neg = x.neg;
if self.form.is_finite() {
self.exp = x.exp;
self.mant.clear();
self.mant.as_mut_vec().extend(x.mant.iter());
}
if self.prec == 0 {
self.prec = x.prec;
} else if self.prec < x.prec {
self.round(0);
}
}
fn fnorm(nat: &mut Nat) -> usize {
if nat.is_nan() {0}
else {
let s = nat.as_vec().last().unwrap().leading_zeros() as usize;
if s > 0 {
let c = unsafe {
shl_vu_inner(nat.as_mut_vec().as_mut_ptr(), nat.as_vec().as_ptr(), s, nat.as_vec().len())
};
assert_eq!(c, 0, "carry must be the 0");
}
s
}
}
fn make_accuracy(is_above: bool) -> Accuracy {
if is_above {
Accuracy::Above
} else {
Accuracy::Below
}
}
fn round(&mut self, mut sbit: usize) {
self.acc = Accuracy::Exact;
if !self.form.is_finite() {
return;
}
let m = self.mant.as_vec().len();
let bits = m << 5;
if bits <= self.prec {
return;
}
let r = bits - self.prec - 1; let rbit = match self.mant.is_set_bit(r) {
Some(true) => 1,
_ => 0,
};
if sbit == 0 && (rbit == 0 || self.mode == ToNearestEven) {
sbit = self.mant.sticky(r);
}
sbit &= 1;
let n = (self.prec + 31) >> 5; if m > n {
self.mant.as_mut_vec().rotate_left(m-n); self.mant.as_mut_vec().truncate(n);
}
let ntz = (n<<5) - self.prec;
let lsb = 1 << ntz;
if (rbit | sbit) != 0 {
let mut inc = false;
inc = match self.mode {
ToNegativeInf => self.neg == Negative,
ToZero => inc,
ToNearestEven => rbit != 0 && (sbit != 0 || (self.mant.as_vec()[0] & lsb) != 0),
ToNearestAway => rbit != 0,
AwayFromZero => true,
ToPositiveInf => self.neg != Negative,
};
self.acc = Self::make_accuracy(BISign::from(inc) != self.neg);
unsafe {
if inc {
if add_vw_inner(self.mant.as_mut_vec().as_mut_ptr(), self.mant.as_vec().as_ptr(), lsb, self.mant.as_vec().len()) != 0 {
if self.exp >= Self::max_exp() {
self.form = Form::Inf;
return;
} else {
self.exp += 1;
shr_vu_inner(self.mant.as_mut_vec().as_mut_ptr(), self.mant.as_vec().as_ptr(), 1, self.mant.as_vec().len());
self.mant.as_mut_vec()[n-1] |= 1 << 31;
}
}
}
}
}
self.mant.as_mut_vec()[0] &= !(lsb - 1);
}
fn set_nat(&mut self, x: &Nat, sign: BISign) {
if x.is_nan() {
self.form = Form::Nan;
} else {
let bits = x.bits_len();
if self.prec == 0 {
self.prec = std::cmp::max(bits, 64);
}
self.acc = Accuracy::Exact;
self.neg = sign;
if x == &0u32 {
self.form = Form::Zero;
} else {
self.mant.clear();
self.mant.as_mut_vec().extend(x.iter());
Self::fnorm(&mut self.mant);
self.set_exp_and_round(bits as isize, 0);
}
}
}
fn set_bigint(&mut self, x: &BigInt) {
self.set_nat(&x.nat, x.sign);
}
fn set_rat(&mut self, x: &Rat) {
match x.is_integer() {
Some(true) => {
self.set_bigint(x.numerator());
},
Some(false) => {
let (mut a, b) = (Float::from(x.numerator().clone()), Float::from(x.denominator().clone()));
if self.prec == 0 {
self.prec = std::cmp::max(a.prec, b.prec);
}
a /= b;
*self = a;
},
None => {
self.form = Form::Nan;
}
}
}
fn uquo(&mut self, y: &Float) {
let n = (self.prec >> 5) as isize + 1;
let d = n - (self.mant.as_vec().len() as isize) + (y.mant.as_vec().len() as isize);
let xadj = if d > 0 {
let tmp = self.mant.deep_clone();
tmp.as_mut_vec().resize(((self.mant.as_vec().len() as isize) + d) as usize, 0);
tmp
} else {
self.mant.clone()
};
let d = (xadj.as_vec().len() as isize) - (y.mant.as_vec().len() as isize);
let (quo, rem) = (xadj.clone() / y.mant.clone(), xadj.clone() % y.mant.clone());
self.mant.clear();
self.mant.as_mut_vec().extend(quo.iter());
let e = self.exp - y.exp - ((d - (self.mant.as_vec().len() as isize)) << 5);
let sbit = if rem > 0u32 {
1
} else {
0
};
let s = Self::fnorm(&mut self.mant) as isize;
self.set_exp_and_round(e - s, sbit);
}
fn div_inner(&mut self, y: &Float) {
if self.prec == 0 {
self.prec = y.prec;
}
self.neg = BISign::from(self.neg != y.neg);
if self.form.is_finite() && y.form.is_finite() {
self.uquo(y)
} else {
self.acc = Accuracy::Exact;
if (self.form.is_zero() && y.form.is_zero()) || (self.form.is_infinite() && self.form.is_infinite()) {
self.form = Form::Nan;
self.neg = Natural;
} else if self.form.is_zero() || y.form.is_infinite() {
self.form = Form::Zero;
} else {
self.form = Form::Inf;
}
}
}
fn msb32(nat: &Nat) -> u32 {
match nat.as_vec().last() {
Some(&x) => x,
None => 0,
}
}
fn msb64(nat: &Nat) -> u64 {
let mut itr = nat.iter().rev().take(2);
match itr.next() {
Some(&h) => {
match itr.next() {
Some(&l) => ((h as u64) << 32) | (l as u64),
None => (h as u64) << 32,
}
},
None => 0,
}
}
pub fn truncate_to_u64(&self) -> Option<(u64, Accuracy)> {
if self.is_nan() {
None
} else {
if self.form.is_finite() {
if self.neg == Negative {
Some((0, Accuracy::Above))
} else if self.exp <= 0 {
Some((0, Accuracy::Below))
} else if self.exp <= 64 {
let u = Self::msb64(&self.mant) >> (64 - self.exp);
if self.required_min_precision() <= (self.exp as usize) {
Some((u, Accuracy::Exact))
} else {
Some((u, Accuracy::Below))
}
} else {
Some((u64::MAX, Accuracy::Below))
}
} else if self.form.is_zero() {
Some((0, Accuracy::Exact))
} else {
if self.neg == Negative {
Some((0, Accuracy::Above))
} else {
Some((u64::MAX, Accuracy::Below))
}
}
}
}
pub fn truncate_to_i64(&self) -> Option<(i64, Accuracy)> {
if self.is_nan() {
None
} else {
if self.form.is_finite() {
let acc = Self::make_accuracy(self.neg == Negative);
if self.exp <= 0 {
Some((0, acc))
} else if self.exp <= 63 {
let i = (Self::msb64(&self.mant) >> (64 - self.exp)) as i64;
let i = if self.neg == Negative {-i} else {i};
if self.required_min_precision() <= (self.exp as usize) {
Some((i, Accuracy::Exact))
} else {
Some((i, acc))
}
} else if self.neg == Negative {
if self.exp == 64 && self.required_min_precision() == 1 {
Some((i64::MIN, Accuracy::Exact))
} else {
Some((i64::MIN, acc))
}
} else {
Some((i64::MAX, Accuracy::Below))
}
} else if self.form.is_zero() {
Some((0, Accuracy::Exact))
} else {
if self.neg == Negative {
Some((i64::MIN, Accuracy::Above))
} else {
Some((i64::MAX, Accuracy::Below))
}
}
}
}
pub fn to_f32(&self) -> (f32, Accuracy) {
if self.is_nan() {
(f32::NAN, Accuracy::Exact)
} else if self.form.is_finite() {
let (fbits, mbits) = (32, 23);
let ebits = fbits - mbits - 1;
let bias = (1 << (ebits - 1)) - 1;
let (emin, emax) = (1-bias, bias);
let e = self.exp - 1;
let mut p = mbits + 1; if e < emin {
p = mbits + 1 - emin + e;
if p < 0 || (p == 0 && self.mant.sticky((Self::nat_len(&self.mant) << 5) - 1) == 0) {
if self.neg == Negative {
return (-0f32, Accuracy::Above);
} else {
return (0f32, Accuracy::Below);
}
} else if p == 0 {
if self.neg == Negative {
return (-f32::MIN_POSITIVE, Accuracy::Below);
} else {
return (f32::MIN_POSITIVE, Accuracy::Above);
}
}
}
let mut r = Self::default();
r.prec = p as usize;
r.set_float(self);
let e = r.exp - 1;
if r.form.is_infinite() || e > emax {
if self.neg == Negative {
(f32::NEG_INFINITY, Accuracy::Below)
} else {
(f32::INFINITY, Accuracy::Above)
}
} else {
let sign = if self.neg == Negative {
1u32 << (fbits - 1)
} else {0};
let (bexp, mant) = if e < emin {
let p = mbits + 1 - emin + e;
let mant = Self::msb32(&r.mant) >> (fbits - p);
(0, mant)
} else {
let bexp = ((e + bias) << mbits) as u32;
let mant = (Self::msb32(&r.mant) >> ebits) & ((1 << mbits) - 1);
(bexp, mant)
};
(f32::from_bits(sign | bexp | mant), r.acc)
}
} else if self.form.is_zero() {
if self.neg == Negative {
(-0f32, Accuracy::Exact)
} else {
(0f32, Accuracy::Exact)
}
} else if self.form.is_infinite() {
if self.neg == Negative {
(f32::NEG_INFINITY, Accuracy::Exact)
} else {
(f32::INFINITY, Accuracy::Exact)
}
} else {
unreachable!();
}
}
pub fn to_f64(&self) -> (f64, Accuracy) {
if self.is_nan() {
(f64::NAN, Accuracy::Exact)
} else if self.form.is_finite() {
let (fbits, mbits) = (64, 52);
let ebits = fbits - mbits - 1;
let bias = (1<<(ebits - 1)) - 1;
let (emin, emax) = (1-bias, bias);
let e = self.exp - 1;
let mut p = mbits + 1;
if e < emin {
p = mbits + 1 - emin + e;
if p < 0 || (p == 0 && self.mant.sticky((Self::nat_len(&self.mant) << 5) - 1) == 0) {
if self.neg == Negative {
return (-0f64, Accuracy::Above);
} else {
return (0f64, Accuracy::Below);
}
} else if p == 0 {
if self.neg == Negative {
return (f64::MIN_POSITIVE, Accuracy::Below);
} else {
return (f64::MIN_POSITIVE, Accuracy::Above);
}
}
}
let mut r = Self::default();
r.prec = p as usize;
r.set_float(self);
let e = r.exp - 1;
if r.form.is_infinite() || e > emax {
if self.neg == Negative {
(f64::NEG_INFINITY, Accuracy::Below)
} else {
(f64::INFINITY, Accuracy::Above)
}
} else {
let sign = if self.neg == Negative {
1 << (fbits - 1)
} else {0};
let (bexp, mant) = if e < emin {
let p = mbits + 1 - emin + e;
let mant = Self::msb64(&r.mant) >> (fbits - p);
(0, mant)
} else {
let bexp = (e + bias) << mbits;
let mant = (Self::msb64(&r.mant) >> ebits) & ((1 << mbits) - 1);
(bexp as u64, mant)
};
(f64::from_bits(sign | bexp | mant), r.acc)
}
} else if self.form.is_zero() {
if self.neg == Negative {
(-0f64, Accuracy::Exact)
} else {
(0f64, Accuracy::Exact)
}
} else if self.form.is_infinite() {
if self.neg == Negative {
(f64::NEG_INFINITY, Accuracy::Exact)
} else {
(f64::INFINITY, Accuracy::Exact)
}
} else {
unreachable!();
}
}
pub fn abs(&self) -> Float {
let mut z = self.deep_clone();
z.neg = Natural;
z
}
#[inline]
fn nat_len(nat: &Nat) -> usize {
nat.as_vec().len()
}
fn nan() -> Float {
let mut z = Self::default();
z.form = Form::Nan;
z
}
fn set_nan(&mut self) {
self.form = Form::Nan;
}
fn uadd(&mut self, y: &Float) {
let x = self;
let (ex, ey) = (x.exp - ((Self::nat_len(&x.mant) as isize) << 5),
y.exp - ((Self::nat_len(&y.mant) as isize) << 5));
let exp= if ex < ey {
let tmp = y.mant.clone() << ((ey - ex) as usize);
x.mant += tmp;
ex
} else if ex > ey {
x.mant <<= (ex - ey) as usize;
x.mant += y.mant.clone();
ey
} else {
x.mant += y.mant.clone();
ex
};
let tmp = exp + ((Self::nat_len(&x.mant) << 5) as isize) - (Self::fnorm(&mut x.mant) as isize);
x.set_exp_and_round(tmp, 0);
}
fn add_inner(&mut self, y: &Float) {
if self.prec == 0 {
self.prec = y.prec;
}
if self.form.is_finite() && y.form.is_finite() {
let yneg = y.neg;
if self.neg == yneg {
self.uadd(y);
} else {
if self.ucmp(y) > 0 {
self.usub(y);
} else {
let mut tmp = y.deep_clone();
tmp.neg = !self.neg;
tmp.usub(&*self);
*self = tmp;
}
}
if self.form.is_zero() && self.mode == RoundingMode::ToNegativeInf && self.acc == Accuracy::Exact {
self.neg = Negative;
}
} else if self.form.is_infinite() && y.form.is_infinite() && self.neg != y.neg {
self.acc = Accuracy::Exact;
self.form = Form::Nan;
self.neg = BISign::from(false);
} else if self.form.is_infinite() || y.form.is_zero() {
} else {
self.set_float(y);
}
}
fn usub(&mut self, y: &Float) {
let x = self;
let (ex, ey) = (
x.exp - ((Self::nat_len(&x.mant) << 5) as isize),
y.exp - ((Self::nat_len(&y.mant) << 5) as isize),
);
let exp = if ex < ey {
let tmp = y.mant.clone() << ((ey - ex) as usize);
x.mant -= tmp;
ex
} else if ex > ey {
x.mant <<= (ex - ey) as usize;
x.mant -= y.mant.clone();
ey
} else {
x.mant -= y.mant.clone();
ex
};
if x.mant == 0u32 {
x.acc = Accuracy::Exact;
x.form = Form::Zero;
x.neg = Natural;
} else {
let tmp = exp + ((Self::nat_len(&x.mant) << 5) as isize) - (Self::fnorm(&mut x.mant) as isize);
x.set_exp_and_round(tmp, 0);
}
}
fn sub_inner(&mut self, y: &Float) {
if self.prec == 0 {
self.prec = y.prec;
}
if self.form.is_finite() && y.form.is_finite() {
let yneg = y.neg;
if self.neg != yneg {
self.uadd(y);
} else {
if self.ucmp(y) > 0 {
self.usub(y);
} else {
let mut tmp = y.deep_clone();
tmp.neg = !self.neg;
tmp.usub(&*self);
*self = tmp;
}
}
if self.form.is_zero() && self.mode == RoundingMode::ToNegativeInf && self.acc == Accuracy::Exact {
self.neg = Negative;
}
} else if self.form.is_infinite() && y.form.is_infinite() && self.neg == y.neg {
self.acc = Accuracy::Exact;
self.form = Form::Nan;
self.neg = Natural;
} else if self.form.is_zero() && y.form.is_zero() {
self.acc = Accuracy::Exact;
self.form = Form::Zero;
self.neg = BISign::from(self.neg == Negative && y.neg != Negative);
} else if self.form.is_infinite() || y.form.is_zero() {
} else {
self.set_float(y);
}
}
fn umul(&mut self, y: &Float) {
let x = self;
let e = x.exp + y.exp;
x.mant *= y.mant.clone();
let tmp = e - (Self::fnorm(&mut x.mant) as isize);
x.set_exp_and_round(tmp, 0);
}
fn mul_inner(&mut self, y: &Float) {
if self.prec == 0 {
self.prec = y.prec;
}
self.neg = BISign::from(self.neg != y.neg);
if self.form.is_finite() && y.form.is_finite() {
self.umul(y);
} else {
self.acc = Accuracy::Exact;
if (self.form.is_zero() && y.form.is_infinite()) || (self.form.is_infinite() && y.form.is_zero()) {
self.form = Form::Nan;
self.neg = Natural;
} else if self.form.is_infinite() || y.form.is_infinite() {
self.form = Form::Inf;
} else {
self.form = Form::Zero;
}
}
}
fn ucmp(&self, y: &Float) -> isize {
let x = self;
if x.exp < y.exp {
-1
} else if x.exp > y.exp {
1
} else {
let (mut i, mut j) = (Self::nat_len(&x.mant), Self::nat_len(&y.mant));
while i > 0 || j > 0 {
let xm = if i > 0 {
i -= 1;
x.mant.as_vec()[i]
} else {
0
};
let ym = if j > 0 {
j -= 1;
y.mant.as_vec()[j]
} else {
0
};
if xm < ym {
return -1;
} else if xm > ym {
return 1;
}
}
0
}
}
fn ord(&self) -> Option<isize> {
let m = if self.form.is_finite() {
Some(1)
} else if self.form.is_zero() {
Some(0)
} else if self.form.is_infinite() {
Some(2)
} else {
None
};
if self.neg == Negative {
m.map(|x| {-x})
} else {
m
}
}
fn cmp_inner(&self, other: &Float) -> Option<isize> {
let (left, right) = (self.ord(), other.ord());
left.zip(right).map(|(mx, my)| {
if mx < my {
-1
} else if mx > my {
1
} else {
if mx == -1 {
other.ucmp(self)
} else if mx == 1 {
self.ucmp(other)
} else {
0
}
}
})
}
}
impl Neg for Float {
type Output = Self;
fn neg(self) -> Self::Output {
let mut z = self.deep_clone();
z.neg = !z.neg;
z
}
}
impl Default for Float {
fn default() -> Self {
Float {
mode: RoundingMode::ToNearestEven,
acc: Accuracy::Exact,
form: Form::Zero,
neg: BISign::from(false),
prec: 0,
exp: 0,
mant: Nat::nan(),
}
}
}
float_impl_from_basic!(set_u64, u64, u8, u16, u32, u64);
float_impl_from_basic!(set_i64, i64, i8, i16, i32, i64);
float_impl_from_basic!(set_f64, f64, f32, f64);
impl From<BigInt> for Float {
fn from(x: BigInt) -> Self {
let mut z = Self::default();
z.set_bigint(&x);
z
}
}
impl From<Nat> for Float {
fn from(x: Nat) -> Self {
let mut z = Self::default();
z.set_nat(&x, Natural);
z
}
}
impl From<Rat> for Float {
fn from(x: Rat) -> Self {
let mut z = Self::default();
z.set_rat(&x);
z
}
}
impl Div for Float {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
if self.is_nan() || rhs.is_nan() {
Self::nan()
} else {
let mut z = self.deep_clone();
z.div_inner(&rhs);
z
}
}
}
impl DivAssign for Float {
fn div_assign(&mut self, rhs: Self) {
if self.is_nan() || rhs.is_nan() {
self.set_nan();
} else {
self.div_inner(&rhs);
}
}
}
impl Add for Float {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
if self.is_nan() || rhs.is_nan() {
Self::nan()
} else {
let mut z = self.deep_clone();
z.add_inner(&rhs);
z
}
}
}
impl AddAssign for Float {
fn add_assign(&mut self, rhs: Self) {
if self.is_nan() || rhs.is_nan() {
self.set_nan();
} else {
self.add_inner(&rhs);
}
}
}
impl Sub for Float {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
if self.is_nan() || rhs.is_nan() {
Self::nan()
} else {
let mut z = self.deep_clone();
z.sub_inner(&rhs);
z
}
}
}
impl SubAssign for Float {
fn sub_assign(&mut self, rhs: Self) {
if self.is_nan() || rhs.is_nan() {
self.set_nan();
} else {
self.sub_inner(&rhs);
}
}
}
impl Mul for Float {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
if self.is_nan() || rhs.is_nan() {
Self::nan()
} else {
let mut z= self.deep_clone();
z.mul_inner(&rhs);
z
}
}
}
impl MulAssign for Float {
fn mul_assign(&mut self, rhs: Self) {
if self.is_nan() || rhs.is_nan() {
self.set_nan();
} else {
self.mul_inner(&rhs);
}
}
}
impl PartialEq for Float {
fn eq(&self, other: &Self) -> bool {
match self.cmp_inner(other) {
Some(x) => x == 0,
None => false,
}
}
}
impl PartialOrd for Float {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.cmp_inner(other).map(|x| {
if x > 0 {
Ordering::Greater
} else if x < 0 {
Ordering::Less
} else {
Ordering::Equal
}
})
}
}