#![allow(deprecated)]
use crate::float::{BorrowFloat, MiniFloat, ToMini};
use crate::{Assign, Float};
use core::fmt::{Debug, Formatter, Result as FmtResult};
use core::marker::PhantomData;
use core::ops::Deref;
use gmp_mpfr_sys::gmp::limb_t;
static ZERO_MINI: MiniFloat = MiniFloat::new();
static ZERO_BORROW: BorrowFloat = ZERO_MINI.borrow();
static ZERO: &Float = BorrowFloat::const_deref(&ZERO_BORROW);
#[deprecated(since = "1.23.0", note = "use `MiniFloat` instead")]
#[derive(Clone)]
pub struct SmallFloat {
inner: Option<Float>,
phantom: PhantomData<*const limb_t>,
}
unsafe impl Send for SmallFloat {}
impl Default for SmallFloat {
#[inline]
fn default() -> Self {
SmallFloat::new()
}
}
impl Debug for SmallFloat {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match &self.inner {
Some(fl) => Debug::fmt(fl, f),
None => Debug::fmt(ZERO, f),
}
}
}
impl SmallFloat {
#[inline]
pub const fn new() -> Self {
SmallFloat {
inner: None,
phantom: PhantomData,
}
}
#[inline]
pub unsafe fn as_nonreallocating_float(&mut self) -> &mut Float {
if self.inner.is_none() {
*self = SmallFloat {
inner: Some(Float::new(ZERO.prec())),
phantom: PhantomData,
};
}
match &mut self.inner {
Some(f) => f,
None => unreachable!(),
}
}
}
impl Deref for SmallFloat {
type Target = Float;
#[inline]
fn deref(&self) -> &Float {
match &self.inner {
Some(f) => f,
None => ZERO,
}
}
}
#[deprecated(since = "1.23.0", note = "`ToMini` instead")]
pub trait ToSmall: ToMini {}
impl<T: ToMini> ToSmall for T {}
impl<T: ToSmall> Assign<T> for SmallFloat {
#[inline]
fn assign(&mut self, src: T) {
let mut mini = MiniFloat::from(src);
unsafe {
let dst = self.as_nonreallocating_float();
let src = mini.borrow_excl();
dst.set_prec(src.prec());
dst.assign(src);
}
}
}
impl<T: ToSmall> From<T> for SmallFloat {
#[inline]
fn from(src: T) -> Self {
let mut mini = MiniFloat::from(src);
let src = mini.borrow_excl();
SmallFloat {
inner: Some(Float::with_val(src.prec(), src)),
phantom: PhantomData,
}
}
}
impl Assign<&Self> for SmallFloat {
#[inline]
fn assign(&mut self, other: &Self) {
self.clone_from(other);
}
}
impl Assign for SmallFloat {
#[inline]
fn assign(&mut self, other: Self) {
*self = other;
}
}
#[cfg(test)]
#[allow(clippy::float_cmp)]
mod tests {
use crate::Assign;
use crate::float;
use crate::float::{FreeCache, SmallFloat, Special};
#[test]
fn check_assign() {
let mut f = SmallFloat::from(-1.0f32);
assert_eq!(*f, -1.0);
f.assign(-2.0f64);
assert_eq!(*f, -2.0);
let other = SmallFloat::from(4u8);
f.assign(&other);
assert_eq!(*f, 4);
f.assign(5i8);
assert_eq!(*f, 5);
f.assign(other);
assert_eq!(*f, 4);
f.assign(6u16);
assert_eq!(*f, 6);
f.assign(-6i16);
assert_eq!(*f, -6);
f.assign(6u32);
assert_eq!(*f, 6);
f.assign(-6i32);
assert_eq!(*f, -6);
f.assign(6u64);
assert_eq!(*f, 6);
f.assign(-6i64);
assert_eq!(*f, -6);
f.assign(6u128);
assert_eq!(*f, 6);
f.assign(-6i128);
assert_eq!(*f, -6);
f.assign(6usize);
assert_eq!(*f, 6);
f.assign(-6isize);
assert_eq!(*f, -6);
f.assign(0u32);
assert_eq!(*f, 0);
f.assign(Special::Infinity);
assert!(f.is_infinite() && f.is_sign_positive());
f.assign(Special::NegZero);
assert!(f.is_zero() && f.is_sign_negative());
f.assign(Special::NegInfinity);
assert!(f.is_infinite() && f.is_sign_negative());
f.assign(Special::Zero);
assert!(f.is_zero() && f.is_sign_positive());
f.assign(Special::Nan);
assert!(f.is_nan());
float::free_cache(FreeCache::All);
}
}