malachite_nz/natural/arithmetic/checked_sub_mul.rs
1// Copyright © 2026 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::natural::InnerNatural::{Large, Small};
10use crate::natural::Natural;
11use crate::natural::arithmetic::sub_mul::{
12 limbs_sub_mul, limbs_sub_mul_in_place_left, limbs_sub_mul_limb_greater,
13 limbs_sub_mul_limb_greater_in_place_left,
14};
15use crate::platform::Limb;
16use malachite_base::num::arithmetic::traits::{CheckedSub, CheckedSubMul};
17use malachite_base::num::basic::traits::Zero;
18
19macro_rules! large_left {
20 ($a_limbs: ident, $b_limbs: ident, $c_limbs: ident) => {
21 (
22 Natural(Large($a_limbs)),
23 Natural(Large($b_limbs)),
24 Natural(Large($c_limbs)),
25 )
26 };
27}
28
29macro_rules! large_right {
30 ($self: ident, $a_limbs: ident, $b_limbs: ident, $c_limbs: ident) => {{
31 let borrow = $a_limbs.len() < $b_limbs.len() + $c_limbs.len() - 1
32 || limbs_sub_mul_in_place_left($a_limbs, &$b_limbs, &$c_limbs);
33 if !borrow {
34 $self.trim();
35 }
36 borrow
37 }};
38}
39
40impl Natural {
41 fn checked_sub_mul_limb_ref_ref(&self, b: &Self, c: Limb) -> Option<Self> {
42 match (self, b, c) {
43 (a, _, 0) | (a, &Self::ZERO, _) => Some(a.clone()),
44 (a, b @ Self(Small(_)), c) => a.checked_sub(b * Self::from(c)),
45 (Self(Small(_)), _, _) => None,
46 (Self(Large(a_limbs)), Self(Large(b_limbs)), c) => {
47 if a_limbs.len() >= b_limbs.len() {
48 limbs_sub_mul_limb_greater(a_limbs, b_limbs, c).map(Self::from_owned_limbs_asc)
49 } else {
50 None
51 }
52 }
53 }
54 }
55
56 fn sub_mul_assign_limb_no_panic(&mut self, b: Self, c: Limb) -> bool {
57 match (&mut *self, b, c) {
58 (_, _, 0) | (_, Self::ZERO, _) => false,
59 (a, b @ Self(Small(_)), c) => a.sub_assign_no_panic(b * Self::from(c)),
60 (Self(Small(_)), _, _) => true,
61 (Self(Large(a_limbs)), Self(Large(b_limbs)), c) => {
62 let borrow = a_limbs.len() < b_limbs.len()
63 || limbs_sub_mul_limb_greater_in_place_left(a_limbs, &b_limbs, c) != 0;
64 if !borrow {
65 self.trim();
66 }
67 borrow
68 }
69 }
70 }
71
72 fn sub_mul_assign_limb_ref_no_panic(&mut self, b: &Self, c: Limb) -> bool {
73 match (&mut *self, b, c) {
74 (_, _, 0) | (_, &Self::ZERO, _) => false,
75 (a, b @ Self(Small(_)), c) => a.sub_assign_no_panic(b * Self::from(c)),
76 (Self(Small(_)), _, _) => true,
77 (Self(Large(a_limbs)), Self(Large(b_limbs)), c) => {
78 let borrow = a_limbs.len() < b_limbs.len()
79 || limbs_sub_mul_limb_greater_in_place_left(a_limbs, b_limbs, c) != 0;
80 if !borrow {
81 self.trim();
82 }
83 borrow
84 }
85 }
86 }
87
88 pub(crate) fn sub_mul_assign_no_panic(&mut self, b: Self, c: Self) -> bool {
89 match (&mut *self, b, c) {
90 (a, Self(Small(small_b)), c) => a.sub_mul_assign_limb_no_panic(c, small_b),
91 (a, b, Self(Small(small_c))) => a.sub_mul_assign_limb_no_panic(b, small_c),
92 (Self(Small(_)), _, _) => true,
93 large_left!(a_limbs, b_limbs, c_limbs) => large_right!(self, a_limbs, b_limbs, c_limbs),
94 }
95 }
96
97 pub(crate) fn sub_mul_assign_val_ref_no_panic(&mut self, b: Self, c: &Self) -> bool {
98 match (&mut *self, &b, c) {
99 (a, Self(Small(small_b)), c) => a.sub_mul_assign_limb_ref_no_panic(c, *small_b),
100 (a, _, Self(Small(small_c))) => a.sub_mul_assign_limb_no_panic(b, *small_c),
101 (Self(Small(_)), _, _) => true,
102 large_left!(a_limbs, b_limbs, c_limbs) => large_right!(self, a_limbs, b_limbs, c_limbs),
103 }
104 }
105
106 pub(crate) fn sub_mul_assign_ref_val_no_panic(&mut self, b: &Self, c: Self) -> bool {
107 match (&mut *self, b, &c) {
108 (a, Self(Small(small_b)), _) => a.sub_mul_assign_limb_no_panic(c, *small_b),
109 (a, b, Self(Small(small_c))) => a.sub_mul_assign_limb_ref_no_panic(b, *small_c),
110 (Self(Small(_)), _, _) => true,
111 large_left!(a_limbs, b_limbs, c_limbs) => large_right!(self, a_limbs, b_limbs, c_limbs),
112 }
113 }
114
115 pub(crate) fn sub_mul_assign_ref_ref_no_panic(&mut self, b: &Self, c: &Self) -> bool {
116 match (&mut *self, b, c) {
117 (a, Self(Small(small_b)), c) => a.sub_mul_assign_limb_ref_no_panic(c, *small_b),
118 (a, b, Self(Small(small_c))) => a.sub_mul_assign_limb_ref_no_panic(b, *small_c),
119 (Self(Small(_)), _, _) => true,
120 large_left!(a_limbs, b_limbs, c_limbs) => large_right!(self, a_limbs, b_limbs, c_limbs),
121 }
122 }
123}
124
125impl CheckedSubMul<Self, Self> for Natural {
126 type Output = Self;
127
128 /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking all three by value
129 /// and returning `None` if the result is negative.
130 ///
131 /// $$
132 /// f(x, y, z) = \\begin{cases}
133 /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\
134 /// \operatorname{None} & \text{otherwise}.
135 /// \\end{cases}
136 /// $$
137 ///
138 /// # Worst-case complexity
139 /// $T(n, m) = O(m + n \log n \log\log n)$
140 ///
141 /// $M(n) = O(n \log n)$
142 ///
143 /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
144 /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
145 ///
146 /// # Panics
147 /// Panics if `y * z` is greater than `self`.
148 ///
149 /// # Examples
150 /// ```
151 /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow};
152 /// use malachite_base::strings::ToDebugString;
153 /// use malachite_nz::natural::Natural;
154 ///
155 /// assert_eq!(
156 /// Natural::from(20u32)
157 /// .checked_sub_mul(Natural::from(3u32), Natural::from(4u32))
158 /// .to_debug_string(),
159 /// "Some(8)"
160 /// );
161 /// assert_eq!(
162 /// Natural::from(10u32)
163 /// .checked_sub_mul(Natural::from(3u32), Natural::from(4u32))
164 /// .to_debug_string(),
165 /// "None"
166 /// );
167 /// assert_eq!(
168 /// Natural::from(10u32)
169 /// .pow(12)
170 /// .checked_sub_mul(Natural::from(0x10000u32), Natural::from(0x10000u32))
171 /// .to_debug_string(),
172 /// "Some(995705032704)"
173 /// );
174 /// ```
175 fn checked_sub_mul(mut self, y: Self, z: Self) -> Option<Self> {
176 if self.sub_mul_assign_no_panic(y, z) {
177 None
178 } else {
179 Some(self)
180 }
181 }
182}
183
184impl<'a> CheckedSubMul<Self, &'a Self> for Natural {
185 type Output = Self;
186
187 /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first two by
188 /// value and the third by reference and returning `None` if the result is negative.
189 ///
190 /// $$
191 /// f(x, y, z) = \\begin{cases}
192 /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\
193 /// \operatorname{None} & \text{otherwise}.
194 /// \\end{cases}
195 /// $$
196 ///
197 /// # Worst-case complexity
198 /// $T(n, m) = O(m + n \log n \log\log n)$
199 ///
200 /// $M(n) = O(n \log n)$
201 ///
202 /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
203 /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
204 ///
205 /// # Panics
206 /// Panics if `y * z` is greater than `self`.
207 ///
208 /// # Examples
209 /// ```
210 /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow};
211 /// use malachite_base::strings::ToDebugString;
212 /// use malachite_nz::natural::Natural;
213 ///
214 /// assert_eq!(
215 /// Natural::from(20u32)
216 /// .checked_sub_mul(Natural::from(3u32), &Natural::from(4u32))
217 /// .to_debug_string(),
218 /// "Some(8)"
219 /// );
220 /// assert_eq!(
221 /// Natural::from(10u32)
222 /// .checked_sub_mul(Natural::from(3u32), &Natural::from(4u32))
223 /// .to_debug_string(),
224 /// "None"
225 /// );
226 /// assert_eq!(
227 /// Natural::from(10u32)
228 /// .pow(12)
229 /// .checked_sub_mul(Natural::from(0x10000u32), &Natural::from(0x10000u32))
230 /// .to_debug_string(),
231 /// "Some(995705032704)"
232 /// );
233 /// ```
234 fn checked_sub_mul(mut self, y: Self, z: &'a Self) -> Option<Self> {
235 if self.sub_mul_assign_val_ref_no_panic(y, z) {
236 None
237 } else {
238 Some(self)
239 }
240 }
241}
242
243impl<'a> CheckedSubMul<&'a Self, Self> for Natural {
244 type Output = Self;
245
246 /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first and third
247 /// by value and the second by reference and returning `None` if the result is negative.
248 ///
249 /// $$
250 /// f(x, y, z) = \\begin{cases}
251 /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\
252 /// \operatorname{None} & \text{otherwise}.
253 /// \\end{cases}
254 /// $$
255 ///
256 /// # Worst-case complexity
257 /// $T(n, m) = O(m + n \log n \log\log n)$
258 ///
259 /// $M(n) = O(n \log n)$
260 ///
261 /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
262 /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
263 ///
264 /// # Panics
265 /// Panics if `y * z` is greater than `self`.
266 ///
267 /// # Examples
268 /// ```
269 /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow};
270 /// use malachite_base::strings::ToDebugString;
271 /// use malachite_nz::natural::Natural;
272 ///
273 /// assert_eq!(
274 /// Natural::from(20u32)
275 /// .checked_sub_mul(&Natural::from(3u32), Natural::from(4u32))
276 /// .to_debug_string(),
277 /// "Some(8)"
278 /// );
279 /// assert_eq!(
280 /// Natural::from(10u32)
281 /// .checked_sub_mul(&Natural::from(3u32), Natural::from(4u32))
282 /// .to_debug_string(),
283 /// "None"
284 /// );
285 /// assert_eq!(
286 /// Natural::from(10u32)
287 /// .pow(12)
288 /// .checked_sub_mul(&Natural::from(0x10000u32), Natural::from(0x10000u32))
289 /// .to_debug_string(),
290 /// "Some(995705032704)"
291 /// );
292 /// ```
293 fn checked_sub_mul(mut self, y: &'a Self, z: Self) -> Option<Self> {
294 if self.sub_mul_assign_ref_val_no_panic(y, z) {
295 None
296 } else {
297 Some(self)
298 }
299 }
300}
301
302impl<'a, 'b> CheckedSubMul<&'a Self, &'b Self> for Natural {
303 type Output = Self;
304
305 /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first by value
306 /// and the second and third by reference and returning `None` if the result is negative.
307 ///
308 /// $$
309 /// f(x, y, z) = \\begin{cases}
310 /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\
311 /// \operatorname{None} & \text{otherwise}.
312 /// \\end{cases}
313 /// $$
314 ///
315 /// # Worst-case complexity
316 /// $T(n, m) = O(m + n \log n \log\log n)$
317 ///
318 /// $M(n) = O(n \log n)$
319 ///
320 /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
321 /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
322 ///
323 /// # Panics
324 /// Panics if `y * z` is greater than `self`.
325 ///
326 /// # Examples
327 /// ```
328 /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow};
329 /// use malachite_base::strings::ToDebugString;
330 /// use malachite_nz::natural::Natural;
331 ///
332 /// assert_eq!(
333 /// Natural::from(20u32)
334 /// .checked_sub_mul(&Natural::from(3u32), &Natural::from(4u32))
335 /// .to_debug_string(),
336 /// "Some(8)"
337 /// );
338 /// assert_eq!(
339 /// Natural::from(10u32)
340 /// .checked_sub_mul(&Natural::from(3u32), &Natural::from(4u32))
341 /// .to_debug_string(),
342 /// "None"
343 /// );
344 /// assert_eq!(
345 /// Natural::from(10u32)
346 /// .pow(12)
347 /// .checked_sub_mul(&Natural::from(0x10000u32), &Natural::from(0x10000u32))
348 /// .to_debug_string(),
349 /// "Some(995705032704)"
350 /// );
351 /// ```
352 fn checked_sub_mul(mut self, y: &'a Self, z: &'b Self) -> Option<Self> {
353 if self.sub_mul_assign_ref_ref_no_panic(y, z) {
354 None
355 } else {
356 Some(self)
357 }
358 }
359}
360
361impl CheckedSubMul<&Natural, &Natural> for &Natural {
362 type Output = Natural;
363
364 /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking all three by
365 /// reference and returning `None` if the result is negative.
366 ///
367 /// $$
368 /// f(x, y, z) = \\begin{cases}
369 /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\
370 /// \operatorname{None} & \text{otherwise}.
371 /// \\end{cases}
372 /// $$
373 ///
374 /// # Worst-case complexity
375 /// $T(n, m) = O(m + n \log n \log\log n)$
376 ///
377 /// $M(n, m) = O(m + n \log n)$
378 ///
379 /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
380 /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
381 ///
382 /// # Examples
383 /// ```
384 /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow};
385 /// use malachite_base::strings::ToDebugString;
386 /// use malachite_nz::natural::Natural;
387 ///
388 /// assert_eq!(
389 /// (&Natural::from(20u32))
390 /// .checked_sub_mul(&Natural::from(3u32), &Natural::from(4u32))
391 /// .to_debug_string(),
392 /// "Some(8)"
393 /// );
394 /// assert_eq!(
395 /// (&Natural::from(10u32))
396 /// .checked_sub_mul(&Natural::from(3u32), &Natural::from(4u32))
397 /// .to_debug_string(),
398 /// "None"
399 /// );
400 /// assert_eq!(
401 /// (&Natural::from(10u32).pow(12))
402 /// .checked_sub_mul(&Natural::from(0x10000u32), &Natural::from(0x10000u32))
403 /// .to_debug_string(),
404 /// "Some(995705032704)"
405 /// );
406 /// ```
407 fn checked_sub_mul(self, y: &Natural, z: &Natural) -> Option<Natural> {
408 match (self, y, z) {
409 (x, Natural(Small(small_y)), z) => x.checked_sub_mul_limb_ref_ref(z, *small_y),
410 (x, y, Natural(Small(small_z))) => x.checked_sub_mul_limb_ref_ref(y, *small_z),
411 (Natural(Small(_)), _, _) => None,
412 (Natural(Large(x_limbs)), Natural(Large(y_limbs)), Natural(Large(z_limbs))) => {
413 if x_limbs.len() >= y_limbs.len() + z_limbs.len() - 1 {
414 limbs_sub_mul(x_limbs, y_limbs, z_limbs).map(Natural::from_owned_limbs_asc)
415 } else {
416 None
417 }
418 }
419 }
420 }
421}