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}