Skip to main content

malachite_float/float/arithmetic/
fractional_part.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5//      Copyright © 1999-2025 Free Software Foundation, Inc.
6//
7// This file is part of Malachite.
8//
9// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
10// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
11// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
12use crate::emulate_float_to_float_fn;
13use malachite_base::num::basic::floats::PrimitiveFloat;
14
15use crate::Float;
16use crate::InnerFloat::{Finite, Infinity, Zero};
17use core::cmp::Ordering::{self, *};
18use malachite_base::num::arithmetic::traits::{ModPowerOf2, NegAssign, NegModPowerOf2};
19use malachite_base::num::basic::integers::PrimitiveInt;
20use malachite_base::num::conversion::traits::ExactFrom;
21use malachite_base::num::logic::traits::SignificantBits;
22use malachite_base::rounding_modes::RoundingMode::{self, *};
23use malachite_nz::platform::Limb;
24
25impl Float {
26    /// Returns the fractional part of a [`Float`], rounded to the specified precision with the
27    /// specified rounding mode, along with an [`Ordering`] comparing the result to the exact
28    /// fraction. The [`Float`] is taken by value.
29    ///
30    /// The fractional part has the same sign as the input, and the rounding mode rounds the exact
31    /// fraction rather than shaping it: for a negative input, `Floor` rounds the (negative)
32    /// fraction downward. The fractional part of an integer or an infinity is a zero with the
33    /// input's sign, and `NaN` propagates. The [`Ordering`]s compare each result to its exact
34    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
35    ///
36    /// # Worst-case complexity
37    /// $T(n) = O(n)$
38    ///
39    /// $M(n) = O(n)$
40    ///
41    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
42    /// self.significant_bits())`.
43    ///
44    /// # Panics
45    /// Panics if `prec` is zero, or if `rm` is `Exact` and the fraction is not exactly
46    /// representable at the target precision.
47    ///
48    /// # Examples
49    /// ```
50    /// use core::cmp::Ordering::*;
51    /// use malachite_base::rounding_modes::RoundingMode::*;
52    /// use malachite_float::Float;
53    ///
54    /// let x = Float::from(3.25f64);
55    /// assert_eq!(
56    ///     x.fractional_part_prec_round_ref(10, Floor),
57    ///     (Float::from(0.25f64), Equal)
58    /// );
59    /// // the fraction of a negative value is negative, and Floor rounds it downward
60    /// let y = Float::from(-3.375f64);
61    /// assert_eq!(
62    ///     y.fractional_part_prec_round(1, Floor),
63    ///     (Float::from(-0.5f64), Less)
64    /// );
65    /// ```
66    #[inline]
67    pub fn fractional_part_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
68        self.fractional_part_helper(prec, rm)
69    }
70
71    /// Returns the fractional part of a [`Float`], rounded to the specified precision with the
72    /// specified rounding mode, along with an [`Ordering`] comparing the result to the exact
73    /// fraction. The [`Float`] is taken by reference.
74    ///
75    /// The fractional part has the same sign as the input, and the rounding mode rounds the exact
76    /// fraction rather than shaping it: for a negative input, `Floor` rounds the (negative)
77    /// fraction downward. The fractional part of an integer or an infinity is a zero with the
78    /// input's sign, and `NaN` propagates. The [`Ordering`]s compare each result to its exact
79    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
80    ///
81    /// # Worst-case complexity
82    /// $T(n) = O(n)$
83    ///
84    /// $M(n) = O(n)$
85    ///
86    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
87    /// self.significant_bits())`.
88    ///
89    /// # Panics
90    /// Panics if `prec` is zero, or if `rm` is `Exact` and the fraction is not exactly
91    /// representable at the target precision.
92    ///
93    /// # Examples
94    /// ```
95    /// use core::cmp::Ordering::*;
96    /// use malachite_base::rounding_modes::RoundingMode::*;
97    /// use malachite_float::Float;
98    ///
99    /// let x = Float::from(3.25f64);
100    /// assert_eq!(
101    ///     x.fractional_part_prec_round_ref(10, Floor),
102    ///     (Float::from(0.25f64), Equal)
103    /// );
104    /// // the fraction of a negative value is negative, and Floor rounds it downward
105    /// let y = Float::from(-3.375f64);
106    /// assert_eq!(
107    ///     y.fractional_part_prec_round(1, Floor),
108    ///     (Float::from(-0.5f64), Less)
109    /// );
110    /// ```
111    #[inline]
112    pub fn fractional_part_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
113        self.fractional_part_helper(prec, rm)
114    }
115
116    /// Returns the fractional part of a [`Float`], rounded to the specified precision with the
117    /// `Nearest` rounding mode, along with an [`Ordering`] comparing the result to the exact
118    /// fraction. The [`Float`] is taken by value.
119    ///
120    /// The fractional part has the same sign as the input, and the rounding mode rounds the exact
121    /// fraction rather than shaping it: for a negative input, `Floor` rounds the (negative)
122    /// fraction downward. The fractional part of an integer or an infinity is a zero with the
123    /// input's sign, and `NaN` propagates. The [`Ordering`]s compare each result to its exact
124    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
125    ///
126    /// # Worst-case complexity
127    /// $T(n) = O(n)$
128    ///
129    /// $M(n) = O(n)$
130    ///
131    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
132    /// self.significant_bits())`.
133    ///
134    /// # Panics
135    /// Panics if `prec` is zero.
136    ///
137    /// # Examples
138    /// ```
139    /// use core::cmp::Ordering::*;
140    /// use malachite_float::Float;
141    ///
142    /// let x = Float::from(3.25f64);
143    /// assert_eq!(
144    ///     x.fractional_part_prec_ref(10),
145    ///     (Float::from(0.25f64), Equal)
146    /// );
147    /// ```
148    #[inline]
149    pub fn fractional_part_prec(self, prec: u64) -> (Self, Ordering) {
150        self.fractional_part_helper(prec, Nearest)
151    }
152
153    /// Returns the fractional part of a [`Float`], rounded to the specified precision with the
154    /// `Nearest` rounding mode, along with an [`Ordering`] comparing the result to the exact
155    /// fraction. The [`Float`] is taken by reference.
156    ///
157    /// The fractional part has the same sign as the input, and the rounding mode rounds the exact
158    /// fraction rather than shaping it: for a negative input, `Floor` rounds the (negative)
159    /// fraction downward. The fractional part of an integer or an infinity is a zero with the
160    /// input's sign, and `NaN` propagates. The [`Ordering`]s compare each result to its exact
161    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
162    ///
163    /// # Worst-case complexity
164    /// $T(n) = O(n)$
165    ///
166    /// $M(n) = O(n)$
167    ///
168    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
169    /// self.significant_bits())`.
170    ///
171    /// # Panics
172    /// Panics if `prec` is zero.
173    ///
174    /// # Examples
175    /// ```
176    /// use core::cmp::Ordering::*;
177    /// use malachite_float::Float;
178    ///
179    /// let x = Float::from(3.25f64);
180    /// assert_eq!(
181    ///     x.fractional_part_prec_ref(10),
182    ///     (Float::from(0.25f64), Equal)
183    /// );
184    /// ```
185    #[inline]
186    pub fn fractional_part_prec_ref(&self, prec: u64) -> (Self, Ordering) {
187        self.fractional_part_helper(prec, Nearest)
188    }
189
190    /// Returns the fractional part of a [`Float`], rounded to the input's precision with the
191    /// specified rounding mode, along with an [`Ordering`] comparing the result to the exact
192    /// fraction. The [`Float`] is taken by value.
193    ///
194    /// The fractional part has the same sign as the input, and the rounding mode rounds the exact
195    /// fraction rather than shaping it: for a negative input, `Floor` rounds the (negative)
196    /// fraction downward. The fractional part of an integer or an infinity is a zero with the
197    /// input's sign, and `NaN` propagates. The [`Ordering`]s compare each result to its exact
198    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
199    ///
200    /// # Worst-case complexity
201    /// $T(n) = O(n)$
202    ///
203    /// $M(n) = O(n)$
204    ///
205    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
206    ///
207    /// # Panics
208    /// Panics if `rm` is `Exact` and the fraction is not exactly representable at the input's
209    /// precision.
210    ///
211    /// # Examples
212    /// ```
213    /// use core::cmp::Ordering::*;
214    /// use malachite_base::rounding_modes::RoundingMode::*;
215    /// use malachite_float::Float;
216    ///
217    /// let x = Float::from(3.25f64);
218    /// assert_eq!(
219    ///     x.fractional_part_round_ref(Ceiling),
220    ///     (Float::from(0.25f64), Equal)
221    /// );
222    /// ```
223    #[inline]
224    pub fn fractional_part_round(self, rm: RoundingMode) -> (Self, Ordering) {
225        self.fractional_part_helper(self.significant_bits(), rm)
226    }
227
228    /// Returns the fractional part of a [`Float`], rounded to the input's precision with the
229    /// specified rounding mode, along with an [`Ordering`] comparing the result to the exact
230    /// fraction. The [`Float`] is taken by reference.
231    ///
232    /// The fractional part has the same sign as the input, and the rounding mode rounds the exact
233    /// fraction rather than shaping it: for a negative input, `Floor` rounds the (negative)
234    /// fraction downward. The fractional part of an integer or an infinity is a zero with the
235    /// input's sign, and `NaN` propagates. The [`Ordering`]s compare each result to its exact
236    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
237    ///
238    /// # Worst-case complexity
239    /// $T(n) = O(n)$
240    ///
241    /// $M(n) = O(n)$
242    ///
243    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
244    ///
245    /// # Panics
246    /// Panics if `rm` is `Exact` and the fraction is not exactly representable at the input's
247    /// precision.
248    ///
249    /// # Examples
250    /// ```
251    /// use core::cmp::Ordering::*;
252    /// use malachite_base::rounding_modes::RoundingMode::*;
253    /// use malachite_float::Float;
254    ///
255    /// let x = Float::from(3.25f64);
256    /// assert_eq!(
257    ///     x.fractional_part_round_ref(Ceiling),
258    ///     (Float::from(0.25f64), Equal)
259    /// );
260    /// ```
261    #[inline]
262    pub fn fractional_part_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
263        self.fractional_part_helper(self.significant_bits(), rm)
264    }
265
266    /// Returns the fractional part of a [`Float`], rounded to the input's precision with the
267    /// `Nearest` rounding mode, along with an [`Ordering`] comparing the result to the exact
268    /// fraction. The [`Float`] is taken by value.
269    ///
270    /// The fractional part has the same sign as the input, and the rounding mode rounds the exact
271    /// fraction rather than shaping it: for a negative input, `Floor` rounds the (negative)
272    /// fraction downward. The fractional part of an integer or an infinity is a zero with the
273    /// input's sign, and `NaN` propagates. The [`Ordering`]s compare each result to its exact
274    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
275    ///
276    /// # Worst-case complexity
277    /// $T(n) = O(n)$
278    ///
279    /// $M(n) = O(n)$
280    ///
281    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
282    ///
283    /// # Panics
284    /// Never panics.
285    ///
286    /// # Examples
287    /// ```
288    /// use core::cmp::Ordering::*;
289    /// use malachite_float::Float;
290    ///
291    /// let x = Float::from(3.25f64);
292    /// assert_eq!(x.fractional_part_ref(), (Float::from(0.25f64), Equal));
293    /// ```
294    #[inline]
295    pub fn fractional_part(self) -> (Self, Ordering) {
296        self.fractional_part_helper(self.significant_bits(), Nearest)
297    }
298
299    /// Returns the fractional part of a [`Float`], rounded to the input's precision with the
300    /// `Nearest` rounding mode, along with an [`Ordering`] comparing the result to the exact
301    /// fraction. The [`Float`] is taken by reference.
302    ///
303    /// The fractional part has the same sign as the input, and the rounding mode rounds the exact
304    /// fraction rather than shaping it: for a negative input, `Floor` rounds the (negative)
305    /// fraction downward. The fractional part of an integer or an infinity is a zero with the
306    /// input's sign, and `NaN` propagates. The [`Ordering`]s compare each result to its exact
307    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
308    ///
309    /// # Worst-case complexity
310    /// $T(n) = O(n)$
311    ///
312    /// $M(n) = O(n)$
313    ///
314    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
315    ///
316    /// # Panics
317    /// Never panics.
318    ///
319    /// # Examples
320    /// ```
321    /// use core::cmp::Ordering::*;
322    /// use malachite_float::Float;
323    ///
324    /// let x = Float::from(3.25f64);
325    /// assert_eq!(x.fractional_part_ref(), (Float::from(0.25f64), Equal));
326    /// ```
327    #[inline]
328    pub fn fractional_part_ref(&self) -> (Self, Ordering) {
329        self.fractional_part_helper(self.significant_bits(), Nearest)
330    }
331
332    /// Returns the integral and fractional parts of a [`Float`], rounded to the specified
333    /// precisions with the specified rounding mode. The [`Float`] is taken by value.
334    ///
335    /// The integral part is the input truncated toward zero and then correctly rounded to its
336    /// target precision, as by [`Float::round_to_integer_then_prec_round`] with `Down`; the
337    /// fractional part is as by [`Float::fractional_part_prec_round`]. Both parts have the input's
338    /// sign; for an infinity, the integral part is the infinity and the fractional part a signed
339    /// zero, and `NaN` propagates to both parts. The [`Ordering`]s compare each result to its exact
340    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
341    ///
342    /// # Worst-case complexity
343    /// $T(n) = O(n)$
344    ///
345    /// $M(n) = O(n)$
346    ///
347    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(iprec, fprec,
348    /// self.significant_bits())`.
349    ///
350    /// # Panics
351    /// Panics if `iprec` or `fprec` is zero, or if `rm` is `Exact` and either part is not exactly
352    /// representable at its target precision.
353    ///
354    /// # Examples
355    /// ```
356    /// use core::cmp::Ordering::*;
357    /// use malachite_base::rounding_modes::RoundingMode::*;
358    /// use malachite_float::Float;
359    ///
360    /// let x = Float::from(-3.25f64);
361    /// let ((i, io), (f, fo)) = x.integer_and_fractional_parts_prec_round_ref(10, 10, Nearest);
362    /// assert_eq!(i, Float::from(-3i32));
363    /// assert_eq!(f, Float::from(-0.25f64));
364    /// assert_eq!((io, fo), (Equal, Equal));
365    /// ```
366    #[inline]
367    pub fn integer_and_fractional_parts_prec_round(
368        self,
369        iprec: u64,
370        fprec: u64,
371        rm: RoundingMode,
372    ) -> ((Self, Ordering), (Self, Ordering)) {
373        self.integer_and_fractional_parts_helper(iprec, fprec, rm)
374    }
375
376    /// Returns the integral and fractional parts of a [`Float`], rounded to the specified
377    /// precisions with the specified rounding mode. The [`Float`] is taken by reference.
378    ///
379    /// The integral part is the input truncated toward zero and then correctly rounded to its
380    /// target precision, as by [`Float::round_to_integer_then_prec_round`] with `Down`; the
381    /// fractional part is as by [`Float::fractional_part_prec_round`]. Both parts have the input's
382    /// sign; for an infinity, the integral part is the infinity and the fractional part a signed
383    /// zero, and `NaN` propagates to both parts. The [`Ordering`]s compare each result to its exact
384    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
385    ///
386    /// # Worst-case complexity
387    /// $T(n) = O(n)$
388    ///
389    /// $M(n) = O(n)$
390    ///
391    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(iprec, fprec,
392    /// self.significant_bits())`.
393    ///
394    /// # Panics
395    /// Panics if `iprec` or `fprec` is zero, or if `rm` is `Exact` and either part is not exactly
396    /// representable at its target precision.
397    ///
398    /// # Examples
399    /// ```
400    /// use core::cmp::Ordering::*;
401    /// use malachite_base::rounding_modes::RoundingMode::*;
402    /// use malachite_float::Float;
403    ///
404    /// let x = Float::from(-3.25f64);
405    /// let ((i, io), (f, fo)) = x.integer_and_fractional_parts_prec_round_ref(10, 10, Nearest);
406    /// assert_eq!(i, Float::from(-3i32));
407    /// assert_eq!(f, Float::from(-0.25f64));
408    /// assert_eq!((io, fo), (Equal, Equal));
409    /// ```
410    #[inline]
411    pub fn integer_and_fractional_parts_prec_round_ref(
412        &self,
413        iprec: u64,
414        fprec: u64,
415        rm: RoundingMode,
416    ) -> ((Self, Ordering), (Self, Ordering)) {
417        self.integer_and_fractional_parts_helper(iprec, fprec, rm)
418    }
419
420    /// Returns the integral and fractional parts of a [`Float`], rounded to the specified
421    /// precisions with the `Nearest` rounding mode. The [`Float`] is taken by value.
422    ///
423    /// The integral part is the input truncated toward zero and then correctly rounded to its
424    /// target precision, as by [`Float::round_to_integer_then_prec_round`] with `Down`; the
425    /// fractional part is as by [`Float::fractional_part_prec_round`]. Both parts have the input's
426    /// sign; for an infinity, the integral part is the infinity and the fractional part a signed
427    /// zero, and `NaN` propagates to both parts. The [`Ordering`]s compare each result to its exact
428    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
429    ///
430    /// # Worst-case complexity
431    /// $T(n) = O(n)$
432    ///
433    /// $M(n) = O(n)$
434    ///
435    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(iprec, fprec,
436    /// self.significant_bits())`.
437    ///
438    /// # Panics
439    /// Panics if `iprec` or `fprec` is zero.
440    ///
441    /// # Examples
442    /// ```
443    /// use core::cmp::Ordering::*;
444    /// use malachite_float::Float;
445    ///
446    /// let x = Float::from(3.25f64);
447    /// let ((i, io), (f, fo)) = x.integer_and_fractional_parts_prec_ref(10, 10);
448    /// assert_eq!(i, Float::from(3u32));
449    /// assert_eq!(f, Float::from(0.25f64));
450    /// assert_eq!((io, fo), (Equal, Equal));
451    /// ```
452    #[inline]
453    pub fn integer_and_fractional_parts_prec(
454        self,
455        iprec: u64,
456        fprec: u64,
457    ) -> ((Self, Ordering), (Self, Ordering)) {
458        self.integer_and_fractional_parts_helper(iprec, fprec, Nearest)
459    }
460
461    /// Returns the integral and fractional parts of a [`Float`], rounded to the specified
462    /// precisions with the `Nearest` rounding mode. The [`Float`] is taken by reference.
463    ///
464    /// The integral part is the input truncated toward zero and then correctly rounded to its
465    /// target precision, as by [`Float::round_to_integer_then_prec_round`] with `Down`; the
466    /// fractional part is as by [`Float::fractional_part_prec_round`]. Both parts have the input's
467    /// sign; for an infinity, the integral part is the infinity and the fractional part a signed
468    /// zero, and `NaN` propagates to both parts. The [`Ordering`]s compare each result to its exact
469    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
470    ///
471    /// # Worst-case complexity
472    /// $T(n) = O(n)$
473    ///
474    /// $M(n) = O(n)$
475    ///
476    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(iprec, fprec,
477    /// self.significant_bits())`.
478    ///
479    /// # Panics
480    /// Panics if `iprec` or `fprec` is zero.
481    ///
482    /// # Examples
483    /// ```
484    /// use core::cmp::Ordering::*;
485    /// use malachite_float::Float;
486    ///
487    /// let x = Float::from(3.25f64);
488    /// let ((i, io), (f, fo)) = x.integer_and_fractional_parts_prec_ref(10, 10);
489    /// assert_eq!(i, Float::from(3u32));
490    /// assert_eq!(f, Float::from(0.25f64));
491    /// assert_eq!((io, fo), (Equal, Equal));
492    /// ```
493    #[inline]
494    pub fn integer_and_fractional_parts_prec_ref(
495        &self,
496        iprec: u64,
497        fprec: u64,
498    ) -> ((Self, Ordering), (Self, Ordering)) {
499        self.integer_and_fractional_parts_helper(iprec, fprec, Nearest)
500    }
501
502    /// Returns the integral and fractional parts of a [`Float`], rounded to the input's precision
503    /// with the specified rounding mode. The [`Float`] is taken by value.
504    ///
505    /// The integral part is the input truncated toward zero and then correctly rounded to its
506    /// target precision, as by [`Float::round_to_integer_then_prec_round`] with `Down`; the
507    /// fractional part is as by [`Float::fractional_part_prec_round`]. Both parts have the input's
508    /// sign; for an infinity, the integral part is the infinity and the fractional part a signed
509    /// zero, and `NaN` propagates to both parts. The [`Ordering`]s compare each result to its exact
510    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
511    ///
512    /// # Worst-case complexity
513    /// $T(n) = O(n)$
514    ///
515    /// $M(n) = O(n)$
516    ///
517    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
518    ///
519    /// # Panics
520    /// Panics if `rm` is `Exact` and the fraction is not exactly representable at the input's
521    /// precision.
522    ///
523    /// # Examples
524    /// ```
525    /// use core::cmp::Ordering::*;
526    /// use malachite_base::rounding_modes::RoundingMode::*;
527    /// use malachite_float::Float;
528    ///
529    /// let x = Float::from(3.25f64);
530    /// let ((i, io), (f, fo)) = x.integer_and_fractional_parts_round_ref(Floor);
531    /// assert_eq!(i, Float::from(3u32));
532    /// assert_eq!(f, Float::from(0.25f64));
533    /// assert_eq!((io, fo), (Equal, Equal));
534    /// ```
535    #[inline]
536    pub fn integer_and_fractional_parts_round(
537        self,
538        rm: RoundingMode,
539    ) -> ((Self, Ordering), (Self, Ordering)) {
540        let prec = self.significant_bits();
541        self.integer_and_fractional_parts_helper(prec, prec, rm)
542    }
543
544    /// Returns the integral and fractional parts of a [`Float`], rounded to the input's precision
545    /// with the specified rounding mode. The [`Float`] is taken by reference.
546    ///
547    /// The integral part is the input truncated toward zero and then correctly rounded to its
548    /// target precision, as by [`Float::round_to_integer_then_prec_round`] with `Down`; the
549    /// fractional part is as by [`Float::fractional_part_prec_round`]. Both parts have the input's
550    /// sign; for an infinity, the integral part is the infinity and the fractional part a signed
551    /// zero, and `NaN` propagates to both parts. The [`Ordering`]s compare each result to its exact
552    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
553    ///
554    /// # Worst-case complexity
555    /// $T(n) = O(n)$
556    ///
557    /// $M(n) = O(n)$
558    ///
559    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
560    ///
561    /// # Panics
562    /// Panics if `rm` is `Exact` and the fraction is not exactly representable at the input's
563    /// precision.
564    ///
565    /// # Examples
566    /// ```
567    /// use core::cmp::Ordering::*;
568    /// use malachite_base::rounding_modes::RoundingMode::*;
569    /// use malachite_float::Float;
570    ///
571    /// let x = Float::from(3.25f64);
572    /// let ((i, io), (f, fo)) = x.integer_and_fractional_parts_round_ref(Floor);
573    /// assert_eq!(i, Float::from(3u32));
574    /// assert_eq!(f, Float::from(0.25f64));
575    /// assert_eq!((io, fo), (Equal, Equal));
576    /// ```
577    #[inline]
578    pub fn integer_and_fractional_parts_round_ref(
579        &self,
580        rm: RoundingMode,
581    ) -> ((Self, Ordering), (Self, Ordering)) {
582        let prec = self.significant_bits();
583        self.integer_and_fractional_parts_helper(prec, prec, rm)
584    }
585
586    /// Returns the integral and fractional parts of a [`Float`], rounded to the input's precision
587    /// with the `Nearest` rounding mode. The [`Float`] is taken by value.
588    ///
589    /// The integral part is the input truncated toward zero and then correctly rounded to its
590    /// target precision, as by [`Float::round_to_integer_then_prec_round`] with `Down`; the
591    /// fractional part is as by [`Float::fractional_part_prec_round`]. Both parts have the input's
592    /// sign; for an infinity, the integral part is the infinity and the fractional part a signed
593    /// zero, and `NaN` propagates to both parts. The [`Ordering`]s compare each result to its exact
594    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
595    ///
596    /// # Worst-case complexity
597    /// $T(n) = O(n)$
598    ///
599    /// $M(n) = O(n)$
600    ///
601    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
602    ///
603    /// # Panics
604    /// Never panics.
605    ///
606    /// # Examples
607    /// ```
608    /// use core::cmp::Ordering::*;
609    /// use malachite_float::Float;
610    ///
611    /// let x = Float::from(3.25f64);
612    /// let ((i, io), (f, fo)) = x.integer_and_fractional_parts_ref();
613    /// assert_eq!(i, Float::from(3u32));
614    /// assert_eq!(f, Float::from(0.25f64));
615    /// assert_eq!((io, fo), (Equal, Equal));
616    /// ```
617    #[inline]
618    pub fn integer_and_fractional_parts(self) -> ((Self, Ordering), (Self, Ordering)) {
619        let prec = self.significant_bits();
620        self.integer_and_fractional_parts_helper(prec, prec, Nearest)
621    }
622
623    /// Returns the integral and fractional parts of a [`Float`], rounded to the input's precision
624    /// with the `Nearest` rounding mode. The [`Float`] is taken by reference.
625    ///
626    /// The integral part is the input truncated toward zero and then correctly rounded to its
627    /// target precision, as by [`Float::round_to_integer_then_prec_round`] with `Down`; the
628    /// fractional part is as by [`Float::fractional_part_prec_round`]. Both parts have the input's
629    /// sign; for an infinity, the integral part is the infinity and the fractional part a signed
630    /// zero, and `NaN` propagates to both parts. The [`Ordering`]s compare each result to its exact
631    /// value; whenever a result equals its exact value, its [`Ordering`] is `Equal`.
632    ///
633    /// # Worst-case complexity
634    /// $T(n) = O(n)$
635    ///
636    /// $M(n) = O(n)$
637    ///
638    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
639    ///
640    /// # Panics
641    /// Never panics.
642    ///
643    /// # Examples
644    /// ```
645    /// use core::cmp::Ordering::*;
646    /// use malachite_float::Float;
647    ///
648    /// let x = Float::from(3.25f64);
649    /// let ((i, io), (f, fo)) = x.integer_and_fractional_parts_ref();
650    /// assert_eq!(i, Float::from(3u32));
651    /// assert_eq!(f, Float::from(0.25f64));
652    /// assert_eq!((io, fo), (Equal, Equal));
653    /// ```
654    #[inline]
655    pub fn integer_and_fractional_parts_ref(&self) -> ((Self, Ordering), (Self, Ordering)) {
656        let prec = self.significant_bits();
657        self.integer_and_fractional_parts_helper(prec, prec, Nearest)
658    }
659
660    // This is mpfr_frac from frac.c, MPFR 4.2.2, with the result's precision passed explicitly.
661    // Rather than MPFR's in-place limb manipulation, the fractional bits are extracted with a mask
662    // and rounded in a single step, which also handles the case of a fraction too small for the
663    // exponent range (MPFR relies on an extended exponent range there).
664    fn fractional_part_helper(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
665        assert_ne!(prec, 0);
666        let Self(Finite {
667            sign,
668            exponent,
669            precision,
670            significand,
671        }) = self
672        else {
673            return match self {
674                Self(Infinity { sign }) => (Self(Zero { sign: *sign }), Equal),
675                _ => (self.clone(), Equal),
676            };
677        };
678        let sign = *sign;
679        let exp = i64::from(*exponent);
680        if exp <= 0 {
681            // 0 < |u| < 1: the value is its own fractional part
682            return Self::from_float_prec_round_ref(self, prec, rm);
683        }
684        let total = i64::exact_from(precision.neg_mod_power_of_2(Limb::LOG_WIDTH) + *precision);
685        if exp >= total {
686            // all significand bits belong to the integer part
687            return (Self(Zero { sign }), Equal);
688        }
689        let frac = significand.mod_power_of_2(u64::exact_from(total - exp));
690        if frac == 0u32 {
691            // u is an integer
692            return (Self(Zero { sign }), Equal);
693        }
694        // The exact fractional part is frac * 2^(exp - total). Negate before rounding, since the
695        // directed rounding modes do not commute with negation.
696        let mut exact = Self::exact_from(frac);
697        if !sign {
698            exact.neg_assign();
699        }
700        exact.shr_prec_round(total - exp, prec, rm)
701    }
702
703    // This is mpfr_modf from modf.c, MPFR 4.2.2, with the two results' precisions passed
704    // explicitly. The integral part is rounded as by [`Float::round_to_integer_then_prec_round`]
705    // with `Down` (truncation, then a rounding to the target precision), and the fractional part as
706    // by [`Float::fractional_part_prec_round`].
707    fn integer_and_fractional_parts_helper(
708        &self,
709        iprec: u64,
710        fprec: u64,
711        rm: RoundingMode,
712    ) -> ((Self, Ordering), (Self, Ordering)) {
713        assert_ne!(iprec, 0);
714        assert_ne!(fprec, 0);
715        let Self(Finite {
716            sign,
717            exponent,
718            precision,
719            ..
720        }) = self
721        else {
722            return match self {
723                Self(Infinity { sign }) => {
724                    ((self.clone(), Equal), (Self(Zero { sign: *sign }), Equal))
725                }
726                _ => ((self.clone(), Equal), (self.clone(), Equal)),
727            };
728        };
729        let sign = *sign;
730        let exp = i64::from(*exponent);
731        if exp <= 0 {
732            // 0 < |u| < 1: the integral part is zero and the fractional part is the value
733            (
734                (Self(Zero { sign }), Equal),
735                Self::from_float_prec_round_ref(self, fprec, rm),
736            )
737        } else if exp >= i64::exact_from(*precision) {
738            // u has no fractional part
739            (
740                Self::from_float_prec_round_ref(self, iprec, rm),
741                (Self(Zero { sign }), Equal),
742            )
743        } else {
744            (
745                self.round_to_integer_then_prec_round_ref(Down, iprec, rm),
746                self.fractional_part_helper(fprec, rm),
747            )
748        }
749    }
750}
751
752/// Computes the fractional part of a primitive float, using emulated [`Float`] arithmetic.
753///
754/// The result is always exactly representable, matching the standard library's `fract` for finite
755/// values with a nonzero fractional part; it serves as a reference implementation. As in
756/// `mpfr_frac`, a zero result takes the input's sign (where `fract` of a negative integer is a
757/// positive zero), and the fractional part of an infinity is a zero of the same sign (where `fract`
758/// returns NaN).
759///
760/// # Worst-case complexity
761/// Constant time and additional memory.
762///
763/// # Examples
764/// ```
765/// use malachite_base::num::float::NiceFloat;
766/// use malachite_float::float::arithmetic::fractional_part::primitive_float_fractional_part;
767///
768/// assert_eq!(
769///     NiceFloat(primitive_float_fractional_part(10.5)),
770///     NiceFloat(0.5)
771/// );
772/// assert_eq!(
773///     NiceFloat(primitive_float_fractional_part(-10.5)),
774///     NiceFloat(-0.5)
775/// );
776/// ```
777#[allow(clippy::type_repetition_in_bounds)]
778#[inline]
779pub fn primitive_float_fractional_part<T: PrimitiveFloat>(x: T) -> T
780where
781    Float: From<T> + PartialOrd<T>,
782    for<'a> T: ExactFrom<&'a Float>,
783{
784    emulate_float_to_float_fn(Float::fractional_part_prec, x)
785}
786
787/// Computes the integer and fractional parts of a primitive float, using emulated [`Float`]
788/// arithmetic.
789///
790/// Both parts are always exactly representable, and their sum is the input; this matches
791/// `x.trunc()` and `x.fract()` for finite values (up to the sign of a zero fraction, which follows
792/// the input as in `mpfr_modf`) and serves as a reference implementation. An infinity keeps its
793/// integer part and has a zero fraction.
794///
795/// # Worst-case complexity
796/// Constant time and additional memory.
797///
798/// # Examples
799/// ```
800/// use malachite_base::num::float::NiceFloat;
801/// use malachite_float::float::arithmetic::fractional_part::*;
802///
803/// let (i, f) = primitive_float_integer_and_fractional_parts(10.5);
804/// assert_eq!(NiceFloat(i), NiceFloat(10.0));
805/// assert_eq!(NiceFloat(f), NiceFloat(0.5));
806/// ```
807#[allow(clippy::type_repetition_in_bounds)]
808#[inline]
809pub fn primitive_float_integer_and_fractional_parts<T: PrimitiveFloat>(x: T) -> (T, T)
810where
811    Float: From<T> + PartialOrd<T>,
812    for<'a> T: ExactFrom<&'a Float>,
813{
814    (
815        emulate_float_to_float_fn(
816            |x, prec| x.integer_and_fractional_parts_prec(prec, prec).0,
817            x,
818        ),
819        emulate_float_to_float_fn(
820            |x, prec| x.integer_and_fractional_parts_prec(prec, prec).1,
821            x,
822        ),
823    )
824}