use Float;
use inner::Inner;
use gmp_mpfr_sys::gmp;
use gmp_mpfr_sys::mpfr;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::slice;
#[derive(Clone, Debug, Default)]
pub struct OrdFloat {
inner: Float,
}
impl OrdFloat {
pub fn as_float(&self) -> &Float {
&self.inner
}
pub fn as_float_mut(&mut self) -> &mut Float {
&mut self.inner
}
}
impl Hash for OrdFloat {
fn hash<H: Hasher>(&self, state: &mut H) {
let s = &self.inner;
s.get_exp().hash(state);
if s.is_nan() {
return;
}
s.is_sign_negative().hash(state);
if s.is_infinite() {
return;
}
let prec = s.prec();
assert_eq!(prec as usize as u32, prec);
let prec = prec as usize;
let mut limbs = prec / gmp::LIMB_BITS as usize;
if prec % gmp::LIMB_BITS as usize > 0 {
limbs += 1;
};
let slice = unsafe { slice::from_raw_parts(s.inner().d, limbs) };
slice.hash(state);
}
}
impl PartialEq for OrdFloat {
#[inline]
fn eq(&self, other: &OrdFloat) -> bool {
let s = &self.inner;
let o = &other.inner;
if s.is_nan() {
o.is_nan()
} else if s.is_zero() {
o.is_zero() && s.is_sign_negative() == o.is_sign_negative()
} else {
s.eq(o)
}
}
}
impl Eq for OrdFloat {}
impl PartialOrd for OrdFloat {
#[inline]
fn partial_cmp(&self, other: &OrdFloat) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for OrdFloat {
#[inline]
fn cmp(&self, other: &OrdFloat) -> Ordering {
let s = &self.inner;
let o = &other.inner;
if s.is_zero() && o.is_zero() {
s.is_sign_positive().cmp(&o.is_sign_positive())
} else {
match (s.is_nan(), o.is_nan()) {
(false, true) => Ordering::Greater,
(true, false) => Ordering::Less,
(true, true) => Ordering::Equal,
(false, false) => unsafe {
mpfr::cmp(s.inner(), o.inner()).cmp(&0)
},
}
}
}
}
impl From<Float> for OrdFloat {
#[inline]
fn from(f: Float) -> OrdFloat {
OrdFloat { inner: f }
}
}