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_constant_to_float_fn<T: PrimitiveFloat, F: Fn(u64) -> (Float, Ordering)>(f: F) -> T
174where
175 Float: PartialOrd<T>,
176 for<'a> T: ExactFrom<&'a Float>,
177{
178 let (result, o) = f(T::MANTISSA_WIDTH + 1);
179 emulate_finish(result, o)
180}
181
182#[allow(clippy::type_repetition_in_bounds)]
183#[doc(hidden)]
184pub fn emulate_float_float_to_float_fn<
185 T: PrimitiveFloat,
186 F: Fn(Float, Float, u64) -> (Float, Ordering),
187>(
188 f: F,
189 x: T,
190 y: T,
191) -> T
192where
193 Float: From<T> + PartialOrd<T>,
194 for<'a> T: ExactFrom<&'a Float>,
195{
196 let x = Float::from(x);
197 let y = Float::from(y);
198 let (result, o) = f(x, y, T::MANTISSA_WIDTH + 1);
199 emulate_finish(result, o)
200}
201
202#[allow(clippy::type_repetition_in_bounds)]
203#[doc(hidden)]
204pub fn emulate_float_float_float_to_float_fn<
205 T: PrimitiveFloat,
206 F: Fn(Float, Float, Float, u64) -> (Float, Ordering),
207>(
208 f: F,
209 x: T,
210 y: T,
211 z: T,
212) -> T
213where
214 Float: From<T> + PartialOrd<T>,
215 for<'a> T: ExactFrom<&'a Float>,
216{
217 let x = Float::from(x);
218 let y = Float::from(y);
219 let z = Float::from(z);
220 let (result, o) = f(x, y, z, T::MANTISSA_WIDTH + 1);
221 emulate_finish(result, o)
222}
223
224#[allow(clippy::type_repetition_in_bounds)]
225#[doc(hidden)]
226pub fn emulate_float_float_float_float_to_float_fn<
227 T: PrimitiveFloat,
228 F: Fn(Float, Float, Float, Float, u64) -> (Float, Ordering),
229>(
230 f: F,
231 x: T,
232 y: T,
233 z: T,
234 w: T,
235) -> T
236where
237 Float: From<T> + PartialOrd<T>,
238 for<'a> T: ExactFrom<&'a Float>,
239{
240 let x = Float::from(x);
241 let y = Float::from(y);
242 let z = Float::from(z);
243 let w = Float::from(w);
244 let (result, o) = f(x, y, z, w, T::MANTISSA_WIDTH + 1);
245 emulate_finish(result, o)
246}
247
248#[allow(clippy::type_repetition_in_bounds)]
249#[doc(hidden)]
250pub fn emulate_float_slice_to_float_fn<
251 T: PrimitiveFloat,
252 F: Fn(&[Float], u64) -> (Float, Ordering),
253>(
254 f: F,
255 xs: &[T],
256) -> T
257where
258 Float: From<T> + PartialOrd<T>,
259 for<'a> T: ExactFrom<&'a Float>,
260{
261 let xs: alloc::vec::Vec<Float> = xs.iter().map(|&x| Float::from(x)).collect();
262 let (result, o) = f(&xs, T::MANTISSA_WIDTH + 1);
263 emulate_finish(result, o)
264}
265
266#[allow(clippy::type_repetition_in_bounds)]
267#[doc(hidden)]
268pub fn emulate_float_slice_float_slice_to_float_fn<
269 T: PrimitiveFloat,
270 F: Fn(&[Float], &[Float], u64) -> (Float, Ordering),
271>(
272 f: F,
273 xs: &[T],
274 ys: &[T],
275) -> T
276where
277 Float: From<T> + PartialOrd<T>,
278 for<'a> T: ExactFrom<&'a Float>,
279{
280 let xs: alloc::vec::Vec<Float> = xs.iter().map(|&x| Float::from(x)).collect();
281 let ys: alloc::vec::Vec<Float> = ys.iter().map(|&y| Float::from(y)).collect();
282 let (result, o) = f(&xs, &ys, T::MANTISSA_WIDTH + 1);
283 emulate_finish(result, o)
284}
285
286#[allow(clippy::type_repetition_in_bounds)]
287#[doc(hidden)]
288pub fn emulate_float_to_float_and_i64_fn<
289 T: PrimitiveFloat,
290 F: Fn(Float, u64) -> (Float, Ordering, i64),
291>(
292 f: F,
293 x: T,
294) -> (T, i64)
295where
296 Float: From<T> + PartialOrd<T>,
297 for<'a> T: ExactFrom<&'a Float>,
298{
299 let x = Float::from(x);
300 let (result, o, quo) = f(x, T::MANTISSA_WIDTH + 1);
301 (emulate_finish(result, o), quo)
304}
305
306#[allow(clippy::type_repetition_in_bounds)]
307#[doc(hidden)]
308pub fn emulate_float_float_to_float_and_i64_fn<
309 T: PrimitiveFloat,
310 F: Fn(Float, Float, u64) -> (Float, Ordering, i64),
311>(
312 f: F,
313 x: T,
314 y: T,
315) -> (T, i64)
316where
317 Float: From<T> + PartialOrd<T>,
318 for<'a> T: ExactFrom<&'a Float>,
319{
320 let x = Float::from(x);
321 let y = Float::from(y);
322 let (result, o, quo) = f(x, y, T::MANTISSA_WIDTH + 1);
323 (emulate_finish(result, o), quo)
326}
327
328#[allow(clippy::type_repetition_in_bounds)]
329#[doc(hidden)]
330pub fn emulate_rational_to_float_fn<T: PrimitiveFloat, F: Fn(&Rational, u64) -> (Float, Ordering)>(
331 f: F,
332 x: &Rational,
333) -> T
334where
335 Float: PartialOrd<T>,
336 for<'a> T: ExactFrom<&'a Float>,
337{
338 let (result, o) = f(x, T::MANTISSA_WIDTH + 1);
339 emulate_finish(result, o)
340}
341
342#[allow(clippy::type_repetition_in_bounds)]
343#[doc(hidden)]
344pub fn emulate_rational_rational_to_float_fn<
345 T: PrimitiveFloat,
346 F: Fn(&Rational, &Rational, u64) -> (Float, Ordering),
347>(
348 f: F,
349 x: &Rational,
350 y: &Rational,
351) -> T
352where
353 Float: PartialOrd<T>,
354 for<'a> T: ExactFrom<&'a Float>,
355{
356 let (result, o) = f(x, y, T::MANTISSA_WIDTH + 1);
357 emulate_finish(result, o)
358}
359
360pub fn test_overflow(result: &Float, o: Ordering) -> bool {
397 if o == Equal {
398 return false;
399 }
400 *result == Float::INFINITY && o == Greater
401 || *result == Float::NEGATIVE_INFINITY && o == Less
402 || *result > 0u32 && result.abs_is_max_finite_value_with_prec() && o == Less
403 || *result < 0u32 && result.abs_is_max_finite_value_with_prec() && o == Greater
404}
405
406pub fn test_underflow(result: &Float, o: Ordering) -> bool {
438 if o == Equal {
439 return false;
440 }
441 *result == 0u32
442 || *result > 0u32 && result.abs_is_min_positive_value() && o == Greater
443 || *result < 0u32 && result.abs_is_min_positive_value() && o == Less
444}
445
446#[macro_use]
448pub mod float;
449pub use float::{ComparableFloat, ComparableFloatRef, Float};
450pub(crate) use float::{
451 InnerFloat, TWICE_WIDTH, WIDTH_MINUS_1, floor_and_ceiling, significand_bits,
452};
453
454#[cfg(feature = "test_build")]
455pub mod test_util;