use crate::Float;
use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
use malachite_base::comparison::traits::{Max, Min};
use malachite_base::named::Named;
use malachite_base::num::arithmetic::traits::{
IsPowerOf2, NegModPowerOf2, PowerOf2, RoundToMultipleOfPowerOf2,
};
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::traits::{
Infinity as InfinityTrait, NaN as NaNTrait, NegativeInfinity, NegativeOne, NegativeZero, One,
OneHalf, Two, Zero as ZeroTrait,
};
use malachite_base::num::logic::traits::{BitScan, LowMask};
use malachite_base::rounding_modes::RoundingMode::*;
use malachite_nz::natural::Natural;
use malachite_nz::platform::Limb;
#[doc(hidden)]
#[macro_export]
macro_rules! float_zero {
() => {
Float(Zero { sign: true })
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_one {
() => {
Float(Finite {
sign: true,
exponent: 1,
precision: 1,
significand: Natural::HIGH_BIT,
})
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_two {
() => {
Float(Finite {
sign: true,
exponent: 2,
precision: 1,
significand: Natural::HIGH_BIT,
})
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_negative_one {
() => {
Float(Finite {
sign: false,
exponent: 1,
precision: 1,
significand: Natural::HIGH_BIT,
})
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_one_half {
() => {
Float(Finite {
sign: true,
exponent: 0,
precision: 1,
significand: Natural::HIGH_BIT,
})
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_negative_zero {
() => {
Float(Zero { sign: false })
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_infinity {
() => {
Float(Infinity { sign: true })
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_negative_infinity {
() => {
Float(Infinity { sign: false })
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_nan {
() => {
Float(NaN)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_finite {
() => {
Float(Finite { .. })
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_either_infinity {
() => {
Float(Infinity { .. })
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! float_either_zero {
() => {
Float(Zero { .. })
};
}
impl ZeroTrait for Float {
const ZERO: Self = float_zero!();
}
impl One for Float {
const ONE: Self = float_one!();
}
impl Two for Float {
const TWO: Self = float_two!();
}
impl NegativeOne for Float {
const NEGATIVE_ONE: Self = float_negative_one!();
}
impl OneHalf for Float {
const ONE_HALF: Self = float_one_half!();
}
impl NegativeZero for Float {
const NEGATIVE_ZERO: Self = float_negative_zero!();
}
impl InfinityTrait for Float {
const INFINITY: Self = float_infinity!();
}
impl NegativeInfinity for Float {
const NEGATIVE_INFINITY: Self = float_negative_infinity!();
}
impl NaNTrait for Float {
const NAN: Self = float_nan!();
}
impl Default for Float {
fn default() -> Self {
Self::NAN
}
}
impl Min for Float {
const MIN: Self = Self::NEGATIVE_INFINITY;
}
impl Max for Float {
const MAX: Self = Self::INFINITY;
}
impl_named!(Float);
impl Float {
pub const MIN_POSITIVE: Self = Self(Finite {
sign: true,
exponent: Self::MIN_EXPONENT,
precision: 1,
significand: Natural::HIGH_BIT,
});
pub fn min_positive_value_prec(prec: u64) -> Self {
assert_ne!(prec, 0);
Self(Finite {
sign: true,
exponent: Self::MIN_EXPONENT,
precision: prec,
significand: Natural::power_of_2(
prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling)
.0
- 1,
),
})
}
pub fn abs_is_min_positive_value(&self) -> bool {
self.get_exponent() == Some(Self::MIN_EXPONENT)
&& self.significand_ref().unwrap().is_power_of_2()
}
pub fn max_finite_value_with_prec(prec: u64) -> Self {
assert_ne!(prec, 0);
Self(Finite {
sign: true,
exponent: Self::MAX_EXPONENT,
precision: prec,
significand: Natural::low_mask(prec) << prec.neg_mod_power_of_2(Limb::LOG_WIDTH),
})
}
pub fn abs_is_max_finite_value_with_prec(&self) -> bool {
if self.get_exponent() != Some(Self::MAX_EXPONENT) {
return false;
}
let prec = self.get_prec().unwrap();
let lowest_1_index = prec.neg_mod_power_of_2(Limb::LOG_WIDTH);
self.significand_ref()
.unwrap()
.index_of_next_false_bit(lowest_1_index)
.unwrap()
== prec
.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling)
.0
}
pub fn one_prec(prec: u64) -> Self {
assert_ne!(prec, 0);
Self(Finite {
sign: true,
exponent: 1,
precision: prec,
significand: Natural::power_of_2(
prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling)
.0
- 1,
),
})
}
pub fn two_prec(prec: u64) -> Self {
assert_ne!(prec, 0);
Self(Finite {
sign: true,
exponent: 2,
precision: prec,
significand: Natural::power_of_2(
prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling)
.0
- 1,
),
})
}
pub fn negative_one_prec(prec: u64) -> Self {
assert_ne!(prec, 0);
Self(Finite {
sign: false,
exponent: 1,
precision: prec,
significand: Natural::power_of_2(
prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling)
.0
- 1,
),
})
}
pub fn one_half_prec(prec: u64) -> Self {
assert_ne!(prec, 0);
Self(Finite {
sign: true,
exponent: 0,
precision: prec,
significand: Natural::power_of_2(
prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling)
.0
- 1,
),
})
}
}