1#![forbid(unsafe_code)]
36#![allow(
37 unstable_name_collisions,
38 clippy::assertions_on_constants,
39 clippy::cognitive_complexity,
40 clippy::many_single_char_names,
41 clippy::range_plus_one,
42 clippy::suspicious_arithmetic_impl,
43 clippy::suspicious_op_assign_impl,
44 clippy::too_many_arguments,
45 clippy::type_complexity,
46 clippy::upper_case_acronyms,
47 clippy::multiple_bound_locations
48)]
49#![warn(
50 clippy::cast_lossless,
51 clippy::comparison_chain,
52 clippy::explicit_into_iter_loop,
53 clippy::explicit_iter_loop,
54 clippy::filter_map_next,
55 clippy::large_digit_groups,
56 clippy::manual_filter_map,
57 clippy::manual_find_map,
58 clippy::map_flatten,
59 clippy::map_unwrap_or,
60 clippy::match_same_arms,
61 clippy::missing_const_for_fn,
62 clippy::mut_mut,
63 clippy::needless_borrow,
64 clippy::needless_continue,
65 clippy::needless_pass_by_value,
66 clippy::print_stdout,
67 clippy::redundant_closure_for_method_calls,
68 clippy::single_match_else,
69 clippy::trait_duplication_in_bounds,
70 clippy::type_repetition_in_bounds,
71 clippy::uninlined_format_args,
72 clippy::unused_self,
73 clippy::if_not_else,
74 clippy::manual_assert,
75 clippy::range_plus_one,
76 clippy::redundant_else,
77 clippy::semicolon_if_nothing_returned,
78 clippy::cloned_instead_of_copied,
79 clippy::flat_map_option,
80 clippy::unnecessary_wraps,
81 clippy::unnested_or_patterns,
82 clippy::use_self,
83 clippy::trivially_copy_pass_by_ref
84)]
85#![cfg_attr(
86 not(any(feature = "test_build", feature = "random", feature = "std")),
87 no_std
88)]
89
90extern crate alloc;
91
92#[macro_use]
93extern crate malachite_base;
94
95#[cfg(feature = "serde")]
96#[macro_use]
97extern crate serde;
98
99#[cfg(feature = "test_build")]
100extern crate itertools;
101
102use core::cmp::Ordering::{self, *};
103use malachite_base::num::arithmetic::traits::IsPowerOf2;
104use malachite_base::num::basic::floats::PrimitiveFloat;
105use malachite_base::num::basic::traits::{Infinity, NegativeInfinity};
106use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom, SciMantissaAndExponent};
107use malachite_base::rounding_modes::RoundingMode::*;
108use malachite_q::Rational;
109
110#[allow(clippy::type_repetition_in_bounds)]
111#[doc(hidden)]
112pub fn emulate_float_to_float_fn<T: PrimitiveFloat, F: Fn(Float, u64) -> (Float, Ordering)>(
113 f: F,
114 x: T,
115) -> T
116where
117 Float: From<T> + PartialOrd<T>,
118 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
119{
120 let x = Float::from(x);
121 let (mut result, o) = f(x.clone(), T::MANTISSA_WIDTH + 1);
122 if !result.is_normal() {
123 return T::exact_from(&result);
124 }
125 let e = i64::from(<&Float as SciMantissaAndExponent<Float, i32, _>>::sci_exponent(&result));
126 if e < T::MIN_NORMAL_EXPONENT {
127 if e < T::MIN_EXPONENT {
128 let rm =
129 if e == T::MIN_EXPONENT - 1 && result.significand_ref().unwrap().is_power_of_2() {
130 let down = if result > T::ZERO { Less } else { Greater };
131 if o == down { Up } else { Down }
132 } else {
133 Nearest
134 };
135 return T::rounding_from(&result, rm).0;
136 }
137 result = f(x, T::max_precision_for_sci_exponent(e)).0;
138 }
139 if result > T::MAX_FINITE {
140 T::INFINITY
141 } else if result < -T::MAX_FINITE {
142 T::NEGATIVE_INFINITY
143 } else {
144 T::exact_from(&result)
145 }
146}
147
148#[allow(clippy::type_repetition_in_bounds)]
149#[doc(hidden)]
150pub fn emulate_float_float_to_float_fn<
151 T: PrimitiveFloat,
152 F: Fn(Float, Float, u64) -> (Float, Ordering),
153>(
154 f: F,
155 x: T,
156 y: T,
157) -> T
158where
159 Float: From<T> + PartialOrd<T>,
160 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
161{
162 let x = Float::from(x);
163 let y = Float::from(y);
164 let (mut result, o) = f(x.clone(), y.clone(), T::MANTISSA_WIDTH + 1);
165 if !result.is_normal() {
166 return T::exact_from(&result);
167 }
168 let e = i64::from(<&Float as SciMantissaAndExponent<Float, i32, _>>::sci_exponent(&result));
169 if e < T::MIN_NORMAL_EXPONENT {
170 if e < T::MIN_EXPONENT {
171 let rm =
172 if e == T::MIN_EXPONENT - 1 && result.significand_ref().unwrap().is_power_of_2() {
173 let down = if result > T::ZERO { Less } else { Greater };
174 if o == down { Up } else { Down }
175 } else {
176 Nearest
177 };
178 return T::rounding_from(&result, rm).0;
179 }
180 result = f(x, y, T::max_precision_for_sci_exponent(e)).0;
181 }
182 if result > T::MAX_FINITE {
183 T::INFINITY
184 } else if result < -T::MAX_FINITE {
185 T::NEGATIVE_INFINITY
186 } else {
187 T::exact_from(&result)
188 }
189}
190
191#[allow(clippy::type_repetition_in_bounds)]
192#[doc(hidden)]
193pub fn emulate_rational_to_float_fn<T: PrimitiveFloat, F: Fn(&Rational, u64) -> (Float, Ordering)>(
194 f: F,
195 x: &Rational,
196) -> T
197where
198 Float: PartialOrd<T>,
199 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
200{
201 let (mut result, o) = f(x, T::MANTISSA_WIDTH + 1);
202 if !result.is_normal() {
203 return T::exact_from(&result);
204 }
205 let e = i64::from(<&Float as SciMantissaAndExponent<Float, i32, _>>::sci_exponent(&result));
206 if e < T::MIN_NORMAL_EXPONENT {
207 if e < T::MIN_EXPONENT {
208 let rm =
209 if e == T::MIN_EXPONENT - 1 && result.significand_ref().unwrap().is_power_of_2() {
210 let down = if result > T::ZERO { Less } else { Greater };
211 if o == down { Up } else { Down }
212 } else {
213 Nearest
214 };
215 return T::rounding_from(&result, rm).0;
216 }
217 result = f(x, T::max_precision_for_sci_exponent(e)).0;
218 }
219 if result > T::MAX_FINITE {
220 T::INFINITY
221 } else if result < -T::MAX_FINITE {
222 T::NEGATIVE_INFINITY
223 } else {
224 T::exact_from(&result)
225 }
226}
227
228#[allow(clippy::type_repetition_in_bounds)]
229#[doc(hidden)]
230pub fn emulate_rational_rational_to_float_fn<
231 T: PrimitiveFloat,
232 F: Fn(&Rational, &Rational, u64) -> (Float, Ordering),
233>(
234 f: F,
235 x: &Rational,
236 y: &Rational,
237) -> T
238where
239 Float: PartialOrd<T>,
240 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
241{
242 let (mut result, o) = f(x, y, T::MANTISSA_WIDTH + 1);
243 if !result.is_normal() {
244 return T::exact_from(&result);
245 }
246 let e = i64::from(<&Float as SciMantissaAndExponent<Float, i32, _>>::sci_exponent(&result));
247 if e < T::MIN_NORMAL_EXPONENT {
248 if e < T::MIN_EXPONENT {
249 let rm =
250 if e == T::MIN_EXPONENT - 1 && result.significand_ref().unwrap().is_power_of_2() {
251 let down = if result > T::ZERO { Less } else { Greater };
252 if o == down { Up } else { Down }
253 } else {
254 Nearest
255 };
256 return T::rounding_from(&result, rm).0;
257 }
258 result = f(x, y, T::max_precision_for_sci_exponent(e)).0;
259 }
260 if result > T::MAX_FINITE {
261 T::INFINITY
262 } else if result < -T::MAX_FINITE {
263 T::NEGATIVE_INFINITY
264 } else {
265 T::exact_from(&result)
266 }
267}
268
269pub fn test_overflow(result: &Float, o: Ordering) -> bool {
306 if o == Equal {
307 return false;
308 }
309 *result == Float::INFINITY && o == Greater
310 || *result == Float::NEGATIVE_INFINITY && o == Less
311 || *result > 0u32 && result.abs_is_max_finite_value_with_prec() && o == Less
312 || *result < 0u32 && result.abs_is_max_finite_value_with_prec() && o == Greater
313}
314
315pub fn test_underflow(result: &Float, o: Ordering) -> bool {
347 if o == Equal {
348 return false;
349 }
350 *result == 0u32
351 || *result > 0u32 && result.abs_is_min_positive_value() && o == Greater
352 || *result < 0u32 && result.abs_is_min_positive_value() && o == Less
353}
354
355#[macro_use]
357pub mod float;
358pub use float::{ComparableFloat, ComparableFloatRef, Float};
359pub(crate) use float::{
360 InnerFloat, TWICE_WIDTH, WIDTH_MINUS_1, floor_and_ceiling, significand_bits,
361};
362
363#[cfg(feature = "test_build")]
364pub mod test_util;