#![forbid(unsafe_code)]
#![allow(
unstable_name_collisions,
clippy::assertions_on_constants,
clippy::cognitive_complexity,
clippy::many_single_char_names,
clippy::range_plus_one,
clippy::suspicious_arithmetic_impl,
clippy::suspicious_op_assign_impl,
clippy::too_many_arguments,
clippy::type_complexity,
clippy::upper_case_acronyms,
clippy::multiple_bound_locations
)]
#![warn(
clippy::cast_lossless,
clippy::comparison_chain,
clippy::explicit_into_iter_loop,
clippy::explicit_iter_loop,
clippy::filter_map_next,
clippy::large_digit_groups,
clippy::manual_filter_map,
clippy::manual_find_map,
clippy::map_flatten,
clippy::map_unwrap_or,
clippy::match_same_arms,
clippy::missing_const_for_fn,
clippy::mut_mut,
clippy::needless_borrow,
clippy::needless_continue,
clippy::needless_pass_by_value,
clippy::print_stdout,
clippy::redundant_closure_for_method_calls,
clippy::single_match_else,
clippy::trait_duplication_in_bounds,
clippy::type_repetition_in_bounds,
clippy::uninlined_format_args,
clippy::unused_self,
clippy::if_not_else,
clippy::manual_assert,
clippy::range_plus_one,
clippy::redundant_else,
clippy::semicolon_if_nothing_returned,
clippy::cloned_instead_of_copied,
clippy::flat_map_option,
clippy::unnecessary_wraps,
clippy::unnested_or_patterns,
clippy::use_self,
clippy::trivially_copy_pass_by_ref
)]
#![cfg_attr(
not(any(feature = "test_build", feature = "random", feature = "std")),
no_std
)]
extern crate alloc;
#[macro_use]
extern crate malachite_base;
#[cfg(feature = "serde")]
#[macro_use]
extern crate serde;
#[macro_use]
mod macros;
#[cfg(feature = "test_build")]
extern crate itertools;
use core::cmp::Ordering::{self, *};
use malachite_base::num::basic::floats::PrimitiveFloat;
use malachite_base::num::basic::traits::{Infinity, NegativeInfinity};
use malachite_base::num::conversion::traits::ExactFrom;
use malachite_base::rounding_modes::RoundingMode::*;
use malachite_q::Rational;
#[allow(clippy::type_repetition_in_bounds)]
fn emulate_finish<T: PrimitiveFloat>(mut result: Float, o: Ordering) -> T
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
if !result.is_normal() {
return T::exact_from(&result);
}
result.subnormalize_assign(o, T::MIN_NORMAL_EXPONENT + 1, Nearest);
if result > T::MAX_FINITE {
T::INFINITY
} else if result < -T::MAX_FINITE {
T::NEGATIVE_INFINITY
} else {
T::exact_from(&result)
}
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_float_to_float_fn<T: PrimitiveFloat, F: Fn(Float, u64) -> (Float, Ordering)>(
f: F,
x: T,
) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let x = Float::from(x);
let (result, o) = f(x, T::MANTISSA_WIDTH + 1);
emulate_finish(result, o)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_float_to_float_pair_fn<
T: PrimitiveFloat,
F: Fn(Float, u64) -> (Float, Float, Ordering, Ordering),
>(
f: F,
x: T,
) -> (T, T)
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let x = Float::from(x);
let (a, b, o_a, o_b) = f(x, T::MANTISSA_WIDTH + 1);
(emulate_finish(a, o_a), emulate_finish(b, o_b))
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_rational_to_float_pair_fn<
T: PrimitiveFloat,
F: Fn(&Rational, u64) -> (Float, Float, Ordering, Ordering),
>(
f: F,
x: &Rational,
) -> (T, T)
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let (a, b, o_a, o_b) = f(x, T::MANTISSA_WIDTH + 1);
(emulate_finish(a, o_a), emulate_finish(b, o_b))
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_constant_to_float_fn<T: PrimitiveFloat, F: Fn(u64) -> (Float, Ordering)>(f: F) -> T
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let (result, o) = f(T::MANTISSA_WIDTH + 1);
emulate_finish(result, o)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_float_float_to_float_fn<
T: PrimitiveFloat,
F: Fn(Float, Float, u64) -> (Float, Ordering),
>(
f: F,
x: T,
y: T,
) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let x = Float::from(x);
let y = Float::from(y);
let (result, o) = f(x, y, T::MANTISSA_WIDTH + 1);
emulate_finish(result, o)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_float_float_float_to_float_fn<
T: PrimitiveFloat,
F: Fn(Float, Float, Float, u64) -> (Float, Ordering),
>(
f: F,
x: T,
y: T,
z: T,
) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let x = Float::from(x);
let y = Float::from(y);
let z = Float::from(z);
let (result, o) = f(x, y, z, T::MANTISSA_WIDTH + 1);
emulate_finish(result, o)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_float_float_float_float_to_float_fn<
T: PrimitiveFloat,
F: Fn(Float, Float, Float, Float, u64) -> (Float, Ordering),
>(
f: F,
x: T,
y: T,
z: T,
w: T,
) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let x = Float::from(x);
let y = Float::from(y);
let z = Float::from(z);
let w = Float::from(w);
let (result, o) = f(x, y, z, w, T::MANTISSA_WIDTH + 1);
emulate_finish(result, o)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_float_slice_to_float_fn<
T: PrimitiveFloat,
F: Fn(&[Float], u64) -> (Float, Ordering),
>(
f: F,
xs: &[T],
) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let xs: alloc::vec::Vec<Float> = xs.iter().map(|&x| Float::from(x)).collect();
let (result, o) = f(&xs, T::MANTISSA_WIDTH + 1);
emulate_finish(result, o)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_float_slice_float_slice_to_float_fn<
T: PrimitiveFloat,
F: Fn(&[Float], &[Float], u64) -> (Float, Ordering),
>(
f: F,
xs: &[T],
ys: &[T],
) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let xs: alloc::vec::Vec<Float> = xs.iter().map(|&x| Float::from(x)).collect();
let ys: alloc::vec::Vec<Float> = ys.iter().map(|&y| Float::from(y)).collect();
let (result, o) = f(&xs, &ys, T::MANTISSA_WIDTH + 1);
emulate_finish(result, o)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_float_to_float_and_i64_fn<
T: PrimitiveFloat,
F: Fn(Float, u64) -> (Float, Ordering, i64),
>(
f: F,
x: T,
) -> (T, i64)
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let x = Float::from(x);
let (result, o, quo) = f(x, T::MANTISSA_WIDTH + 1);
(emulate_finish(result, o), quo)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_float_float_to_float_and_i64_fn<
T: PrimitiveFloat,
F: Fn(Float, Float, u64) -> (Float, Ordering, i64),
>(
f: F,
x: T,
y: T,
) -> (T, i64)
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let x = Float::from(x);
let y = Float::from(y);
let (result, o, quo) = f(x, y, T::MANTISSA_WIDTH + 1);
(emulate_finish(result, o), quo)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_rational_to_float_fn<T: PrimitiveFloat, F: Fn(&Rational, u64) -> (Float, Ordering)>(
f: F,
x: &Rational,
) -> T
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let (result, o) = f(x, T::MANTISSA_WIDTH + 1);
emulate_finish(result, o)
}
#[allow(clippy::type_repetition_in_bounds)]
#[doc(hidden)]
pub fn emulate_rational_rational_to_float_fn<
T: PrimitiveFloat,
F: Fn(&Rational, &Rational, u64) -> (Float, Ordering),
>(
f: F,
x: &Rational,
y: &Rational,
) -> T
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
let (result, o) = f(x, y, T::MANTISSA_WIDTH + 1);
emulate_finish(result, o)
}
pub fn test_overflow(result: &Float, o: Ordering) -> bool {
if o == Equal {
return false;
}
*result == Float::INFINITY && o == Greater
|| *result == Float::NEGATIVE_INFINITY && o == Less
|| *result > 0u32 && result.abs_is_max_finite_value_with_prec() && o == Less
|| *result < 0u32 && result.abs_is_max_finite_value_with_prec() && o == Greater
}
pub fn test_underflow(result: &Float, o: Ordering) -> bool {
if o == Equal {
return false;
}
*result == 0u32
|| *result > 0u32 && result.abs_is_min_positive_value() && o == Greater
|| *result < 0u32 && result.abs_is_min_positive_value() && o == Less
}
#[macro_use]
pub mod float;
pub use float::{ComparableFloat, ComparableFloatRef, Float};
pub(crate) use float::{
InnerFloat, TWICE_WIDTH, WIDTH_MINUS_1, floor_and_ceiling, significand_bits,
};
#[cfg(feature = "test_build")]
pub mod test_util;