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}