1#![forbid(unsafe_code)]
58#![allow(
59 unstable_name_collisions,
60 clippy::assertions_on_constants,
61 clippy::cognitive_complexity,
62 clippy::many_single_char_names,
63 clippy::range_plus_one,
64 clippy::suspicious_arithmetic_impl,
65 clippy::suspicious_op_assign_impl,
66 clippy::too_many_arguments,
67 clippy::type_complexity,
68 clippy::upper_case_acronyms,
69 clippy::multiple_bound_locations
70)]
71#![warn(
72 clippy::cast_lossless,
73 clippy::comparison_chain,
74 clippy::explicit_into_iter_loop,
75 clippy::explicit_iter_loop,
76 clippy::filter_map_next,
77 clippy::large_digit_groups,
78 clippy::manual_filter_map,
79 clippy::manual_find_map,
80 clippy::map_flatten,
81 clippy::map_unwrap_or,
82 clippy::match_same_arms,
83 clippy::missing_const_for_fn,
84 clippy::mut_mut,
85 clippy::needless_borrow,
86 clippy::needless_continue,
87 clippy::needless_pass_by_value,
88 clippy::print_stdout,
89 clippy::redundant_closure_for_method_calls,
90 clippy::single_match_else,
91 clippy::trait_duplication_in_bounds,
92 clippy::type_repetition_in_bounds,
93 clippy::uninlined_format_args,
94 clippy::unused_self,
95 clippy::if_not_else,
96 clippy::manual_assert,
97 clippy::range_plus_one,
98 clippy::redundant_else,
99 clippy::semicolon_if_nothing_returned,
100 clippy::cloned_instead_of_copied,
101 clippy::flat_map_option,
102 clippy::unnecessary_wraps,
103 clippy::unnested_or_patterns,
104 clippy::use_self,
105 clippy::trivially_copy_pass_by_ref
106)]
107#![cfg_attr(
108 not(any(feature = "test_build", feature = "random", feature = "std")),
109 no_std
110)]
111
112extern crate alloc;
113
114#[macro_use]
115extern crate malachite_base;
116
117#[cfg(feature = "serde")]
118#[macro_use]
119extern crate serde;
120#[macro_use]
121mod macros;
122
123#[cfg(feature = "test_build")]
124extern crate itertools;
125
126use core::cmp::Ordering::{self, *};
127use malachite_base::num::basic::floats::PrimitiveFloat;
128use malachite_base::num::basic::traits::{Infinity, NegativeInfinity};
129use malachite_base::num::conversion::traits::ExactFrom;
130use malachite_base::rounding_modes::RoundingMode::*;
131use malachite_q::Rational;
132
133#[allow(clippy::type_repetition_in_bounds)]
134fn emulate_finish<T: PrimitiveFloat>(mut result: Float, o: Ordering) -> T
135where
136 Float: PartialOrd<T>,
137 for<'a> T: ExactFrom<&'a Float>,
138{
139 if !result.is_normal() {
140 return T::exact_from(&result);
141 }
142 result.subnormalize_assign(o, T::MIN_NORMAL_EXPONENT + 1, Nearest);
147 if result > T::MAX_FINITE {
148 T::INFINITY
149 } else if result < -T::MAX_FINITE {
150 T::NEGATIVE_INFINITY
151 } else {
152 T::exact_from(&result)
153 }
154}
155
156#[allow(clippy::type_repetition_in_bounds)]
157#[doc(hidden)]
158pub fn emulate_float_to_float_fn<T: PrimitiveFloat, F: Fn(Float, u64) -> (Float, Ordering)>(
159 f: F,
160 x: T,
161) -> T
162where
163 Float: From<T> + PartialOrd<T>,
164 for<'a> T: ExactFrom<&'a Float>,
165{
166 let x = Float::from(x);
167 let (result, o) = f(x, T::MANTISSA_WIDTH + 1);
168 emulate_finish(result, o)
169}
170
171#[allow(clippy::type_repetition_in_bounds)]
172#[doc(hidden)]
173pub fn emulate_float_to_float_pair_fn<
174 T: PrimitiveFloat,
175 F: Fn(Float, u64) -> (Float, Float, Ordering, Ordering),
176>(
177 f: F,
178 x: T,
179) -> (T, T)
180where
181 Float: From<T> + PartialOrd<T>,
182 for<'a> T: ExactFrom<&'a Float>,
183{
184 let x = Float::from(x);
185 let (a, b, o_a, o_b) = f(x, T::MANTISSA_WIDTH + 1);
186 (emulate_finish(a, o_a), emulate_finish(b, o_b))
187}
188
189#[allow(clippy::type_repetition_in_bounds)]
190#[doc(hidden)]
191pub fn emulate_rational_to_float_pair_fn<
192 T: PrimitiveFloat,
193 F: Fn(&Rational, u64) -> (Float, Float, Ordering, Ordering),
194>(
195 f: F,
196 x: &Rational,
197) -> (T, T)
198where
199 Float: PartialOrd<T>,
200 for<'a> T: ExactFrom<&'a Float>,
201{
202 let (a, b, o_a, o_b) = f(x, T::MANTISSA_WIDTH + 1);
203 (emulate_finish(a, o_a), emulate_finish(b, o_b))
204}
205
206#[allow(clippy::type_repetition_in_bounds)]
207#[doc(hidden)]
208pub fn emulate_constant_to_float_fn<T: PrimitiveFloat, F: Fn(u64) -> (Float, Ordering)>(f: F) -> T
209where
210 Float: PartialOrd<T>,
211 for<'a> T: ExactFrom<&'a Float>,
212{
213 let (result, o) = f(T::MANTISSA_WIDTH + 1);
214 emulate_finish(result, o)
215}
216
217#[allow(clippy::type_repetition_in_bounds)]
218#[doc(hidden)]
219pub fn emulate_float_float_to_float_fn<
220 T: PrimitiveFloat,
221 F: Fn(Float, Float, u64) -> (Float, Ordering),
222>(
223 f: F,
224 x: T,
225 y: T,
226) -> T
227where
228 Float: From<T> + PartialOrd<T>,
229 for<'a> T: ExactFrom<&'a Float>,
230{
231 let x = Float::from(x);
232 let y = Float::from(y);
233 let (result, o) = f(x, y, T::MANTISSA_WIDTH + 1);
234 emulate_finish(result, o)
235}
236
237#[allow(clippy::type_repetition_in_bounds)]
238#[doc(hidden)]
239pub fn emulate_float_float_float_to_float_fn<
240 T: PrimitiveFloat,
241 F: Fn(Float, Float, Float, u64) -> (Float, Ordering),
242>(
243 f: F,
244 x: T,
245 y: T,
246 z: T,
247) -> T
248where
249 Float: From<T> + PartialOrd<T>,
250 for<'a> T: ExactFrom<&'a Float>,
251{
252 let x = Float::from(x);
253 let y = Float::from(y);
254 let z = Float::from(z);
255 let (result, o) = f(x, y, z, T::MANTISSA_WIDTH + 1);
256 emulate_finish(result, o)
257}
258
259#[allow(clippy::type_repetition_in_bounds)]
260#[doc(hidden)]
261pub fn emulate_float_float_float_float_to_float_fn<
262 T: PrimitiveFloat,
263 F: Fn(Float, Float, Float, Float, u64) -> (Float, Ordering),
264>(
265 f: F,
266 x: T,
267 y: T,
268 z: T,
269 w: T,
270) -> T
271where
272 Float: From<T> + PartialOrd<T>,
273 for<'a> T: ExactFrom<&'a Float>,
274{
275 let x = Float::from(x);
276 let y = Float::from(y);
277 let z = Float::from(z);
278 let w = Float::from(w);
279 let (result, o) = f(x, y, z, w, T::MANTISSA_WIDTH + 1);
280 emulate_finish(result, o)
281}
282
283#[allow(clippy::type_repetition_in_bounds)]
284#[doc(hidden)]
285pub fn emulate_float_slice_to_float_fn<
286 T: PrimitiveFloat,
287 F: Fn(&[Float], u64) -> (Float, Ordering),
288>(
289 f: F,
290 xs: &[T],
291) -> T
292where
293 Float: From<T> + PartialOrd<T>,
294 for<'a> T: ExactFrom<&'a Float>,
295{
296 let xs: alloc::vec::Vec<Float> = xs.iter().map(|&x| Float::from(x)).collect();
297 let (result, o) = f(&xs, T::MANTISSA_WIDTH + 1);
298 emulate_finish(result, o)
299}
300
301#[allow(clippy::type_repetition_in_bounds)]
302#[doc(hidden)]
303pub fn emulate_float_slice_float_slice_to_float_fn<
304 T: PrimitiveFloat,
305 F: Fn(&[Float], &[Float], u64) -> (Float, Ordering),
306>(
307 f: F,
308 xs: &[T],
309 ys: &[T],
310) -> T
311where
312 Float: From<T> + PartialOrd<T>,
313 for<'a> T: ExactFrom<&'a Float>,
314{
315 let xs: alloc::vec::Vec<Float> = xs.iter().map(|&x| Float::from(x)).collect();
316 let ys: alloc::vec::Vec<Float> = ys.iter().map(|&y| Float::from(y)).collect();
317 let (result, o) = f(&xs, &ys, T::MANTISSA_WIDTH + 1);
318 emulate_finish(result, o)
319}
320
321#[allow(clippy::type_repetition_in_bounds)]
322#[doc(hidden)]
323pub fn emulate_float_to_float_and_i64_fn<
324 T: PrimitiveFloat,
325 F: Fn(Float, u64) -> (Float, Ordering, i64),
326>(
327 f: F,
328 x: T,
329) -> (T, i64)
330where
331 Float: From<T> + PartialOrd<T>,
332 for<'a> T: ExactFrom<&'a Float>,
333{
334 let x = Float::from(x);
335 let (result, o, quo) = f(x, T::MANTISSA_WIDTH + 1);
336 (emulate_finish(result, o), quo)
339}
340
341#[allow(clippy::type_repetition_in_bounds)]
342#[doc(hidden)]
343pub fn emulate_float_float_to_float_and_i64_fn<
344 T: PrimitiveFloat,
345 F: Fn(Float, Float, u64) -> (Float, Ordering, i64),
346>(
347 f: F,
348 x: T,
349 y: T,
350) -> (T, i64)
351where
352 Float: From<T> + PartialOrd<T>,
353 for<'a> T: ExactFrom<&'a Float>,
354{
355 let x = Float::from(x);
356 let y = Float::from(y);
357 let (result, o, quo) = f(x, y, T::MANTISSA_WIDTH + 1);
358 (emulate_finish(result, o), quo)
361}
362
363#[allow(clippy::type_repetition_in_bounds)]
364#[doc(hidden)]
365pub fn emulate_rational_to_float_fn<T: PrimitiveFloat, F: Fn(&Rational, u64) -> (Float, Ordering)>(
366 f: F,
367 x: &Rational,
368) -> T
369where
370 Float: PartialOrd<T>,
371 for<'a> T: ExactFrom<&'a Float>,
372{
373 let (result, o) = f(x, T::MANTISSA_WIDTH + 1);
374 emulate_finish(result, o)
375}
376
377#[allow(clippy::type_repetition_in_bounds)]
378#[doc(hidden)]
379pub fn emulate_rational_rational_to_float_fn<
380 T: PrimitiveFloat,
381 F: Fn(&Rational, &Rational, u64) -> (Float, Ordering),
382>(
383 f: F,
384 x: &Rational,
385 y: &Rational,
386) -> T
387where
388 Float: PartialOrd<T>,
389 for<'a> T: ExactFrom<&'a Float>,
390{
391 let (result, o) = f(x, y, T::MANTISSA_WIDTH + 1);
392 emulate_finish(result, o)
393}
394
395pub fn test_overflow(result: &Float, o: Ordering) -> bool {
432 if o == Equal {
433 return false;
434 }
435 *result == Float::INFINITY && o == Greater
436 || *result == Float::NEGATIVE_INFINITY && o == Less
437 || *result > 0u32 && result.abs_is_max_finite_value_with_prec() && o == Less
438 || *result < 0u32 && result.abs_is_max_finite_value_with_prec() && o == Greater
439}
440
441pub fn test_underflow(result: &Float, o: Ordering) -> bool {
473 if o == Equal {
474 return false;
475 }
476 *result == 0u32
477 || *result > 0u32 && result.abs_is_min_positive_value() && o == Greater
478 || *result < 0u32 && result.abs_is_min_positive_value() && o == Less
479}
480
481#[macro_use]
483pub mod float;
484pub use float::{ComparableFloat, ComparableFloatRef, Float};
485pub(crate) use float::{
486 InnerFloat, TWICE_WIDTH, WIDTH_MINUS_1, floor_and_ceiling, significand_bits,
487};
488
489#[cfg(feature = "test_build")]
490pub mod test_util;