malachite_q/arithmetic/
ceiling.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::Rational;
10use core::mem::swap;
11use malachite_base::num::arithmetic::traits::{Ceiling, CeilingAssign, DivRound, DivRoundAssign};
12use malachite_base::num::basic::traits::One;
13use malachite_base::rounding_modes::RoundingMode::*;
14use malachite_nz::integer::Integer;
15use malachite_nz::natural::Natural;
16
17impl Ceiling for Rational {
18    type Output = Integer;
19
20    /// Finds the ceiling of a [`Rational`], taking the [`Rational`] by value.
21    ///
22    /// $$
23    /// f(x) = \lceil x \rceil.
24    /// $$
25    ///
26    /// # Worst-case complexity
27    /// $T(n) = O(n \log n \log\log n)$
28    ///
29    /// $M(n) = O(n \log n)$
30    ///
31    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
32    /// other.significant_bits())`.
33    ///
34    /// # Examples
35    /// ```
36    /// use malachite_base::num::arithmetic::traits::Ceiling;
37    /// use malachite_base::num::basic::traits::Zero;
38    /// use malachite_q::Rational;
39    ///
40    /// assert_eq!(Rational::ZERO.ceiling(), 0);
41    /// assert_eq!(Rational::from_signeds(22, 7).ceiling(), 4);
42    /// assert_eq!(Rational::from_signeds(-22, 7).ceiling(), -3);
43    /// ```
44    fn ceiling(self) -> Integer {
45        if self.sign {
46            Integer::from(self.numerator.div_round(self.denominator, Ceiling).0)
47        } else {
48            Integer::from_sign_and_abs(false, self.numerator / self.denominator)
49        }
50    }
51}
52
53impl Ceiling for &Rational {
54    type Output = Integer;
55
56    /// Finds the ceiling of a [`Rational`], taking the [`Rational`] by reference.
57    ///
58    /// $$
59    /// f(x) = \lceil x \rceil.
60    /// $$
61    ///
62    /// # Worst-case complexity
63    /// $T(n) = O(n \log n \log\log n)$
64    ///
65    /// $M(n) = O(n \log n)$
66    ///
67    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
68    /// other.significant_bits())`.
69    ///
70    /// # Examples
71    /// ```
72    /// use malachite_base::num::arithmetic::traits::Ceiling;
73    /// use malachite_base::num::basic::traits::Zero;
74    /// use malachite_q::Rational;
75    ///
76    /// assert_eq!((&Rational::ZERO).ceiling(), 0);
77    /// assert_eq!((&Rational::from_signeds(22, 7)).ceiling(), 4);
78    /// assert_eq!((&Rational::from_signeds(-22, 7)).ceiling(), -3);
79    /// ```
80    fn ceiling(self) -> Integer {
81        if self.sign {
82            Integer::from((&self.numerator).div_round(&self.denominator, Ceiling).0)
83        } else {
84            Integer::from_sign_and_abs(false, &self.numerator / &self.denominator)
85        }
86    }
87}
88
89impl CeilingAssign for Rational {
90    /// Replaces a [`Rational`] with its ceiling.
91    ///
92    /// $$
93    /// x \gets \lceil x \rceil.
94    /// $$
95    ///
96    /// # Worst-case complexity
97    /// $T(n) = O(n \log n \log\log n)$
98    ///
99    /// $M(n) = O(n \log n)$
100    ///
101    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
102    /// other.significant_bits())`.
103    ///
104    /// # Examples
105    /// ```
106    /// use malachite_base::num::arithmetic::traits::CeilingAssign;
107    /// use malachite_base::num::basic::traits::Zero;
108    /// use malachite_q::Rational;
109    ///
110    /// let mut x = Rational::ZERO;
111    /// x.ceiling_assign();
112    /// assert_eq!(x, 0);
113    ///
114    /// let mut x = Rational::from_signeds(22, 7);
115    /// x.ceiling_assign();
116    /// assert_eq!(x, 4);
117    ///
118    /// let mut x = Rational::from_signeds(-22, 7);
119    /// x.ceiling_assign();
120    /// assert_eq!(x, -3);
121    /// ```
122    fn ceiling_assign(&mut self) {
123        let mut d = Natural::ONE;
124        swap(&mut self.denominator, &mut d);
125        if self.sign {
126            self.numerator.div_round_assign(d, Ceiling);
127        } else {
128            self.numerator /= d;
129            if !self.sign && self.numerator == 0 {
130                self.sign = true;
131            }
132        }
133    }
134}