Skip to main content

malachite_nz/natural/conversion/
to_limbs.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::platform::Limb;
12use alloc::vec::Vec;
13use core::ops::Index;
14use core::slice;
15use malachite_base::num::basic::traits::Zero;
16use malachite_base::num::conversion::traits::ExactFrom;
17
18/// A double-ended iterator over the [limbs](crate#limbs) of a [`Natural`].
19///
20/// The forward order is ascending (least-significant first). The iterator does not iterate over any
21/// implicit leading zero limbs.
22///
23/// This struct also supports retrieving limbs by index. This functionality is completely
24/// independent of the iterator's state. Indexing the implicit leading zero limbs is allowed.
25#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
26pub struct LimbIterator<'a> {
27    pub(crate) n: &'a Natural,
28    pub(crate) limb_count: usize,
29    pub(crate) remaining: usize,
30    // If `n` is nonzero, this index initially points to the least-significant limb, and is
31    // incremented by next().
32    pub(crate) i: u64,
33    // If `n` is nonzero, this index initially points to the most-significant limb, and is
34    // decremented by next_back().
35    pub(crate) j: u64,
36}
37
38impl Iterator for LimbIterator<'_> {
39    type Item = Limb;
40
41    /// A function to iterate through the [limbs](crate#limbs) of a [`Natural`] in ascending order
42    /// (least-significant first).
43    ///
44    /// # Worst-case complexity
45    /// Constant time and additional memory.
46    ///
47    /// # Examples
48    /// ```
49    /// use malachite_base::num::arithmetic::traits::Pow;
50    /// use malachite_base::num::basic::integers::PrimitiveInt;
51    /// use malachite_base::num::basic::traits::Zero;
52    /// use malachite_nz::natural::Natural;
53    /// use malachite_nz::platform::Limb;
54    ///
55    /// if Limb::WIDTH == u32::WIDTH {
56    ///     assert_eq!(Natural::ZERO.limbs().next(), None);
57    ///
58    ///     // 10^12 = 232 * 2^32 + 3567587328
59    ///     let trillion = Natural::from(10u32).pow(12);
60    ///     let mut limbs = trillion.limbs();
61    ///     assert_eq!(limbs.next(), Some(3567587328));
62    ///     assert_eq!(limbs.next(), Some(232));
63    ///     assert_eq!(limbs.next(), None);
64    /// }
65    /// ```
66    fn next(&mut self) -> Option<Limb> {
67        if self.remaining != 0 {
68            let limb = match self.n {
69                Natural(Small(small)) => *small,
70                Natural(Large(limbs)) => limbs[usize::exact_from(self.i)],
71            };
72            if self.i != self.j {
73                self.i += 1;
74            }
75            self.remaining -= 1;
76            Some(limb)
77        } else {
78            None
79        }
80    }
81
82    #[inline]
83    fn size_hint(&self) -> (usize, Option<usize>) {
84        (self.remaining, Some(self.remaining))
85    }
86}
87
88impl DoubleEndedIterator for LimbIterator<'_> {
89    /// A function to iterate through the [limbs](crate#limbs) of a [`Natural`] in descending order
90    /// (most-significant first).
91    ///
92    /// # Worst-case complexity
93    /// Constant time and additional memory.
94    ///
95    /// # Examples
96    /// ```
97    /// use malachite_base::num::arithmetic::traits::Pow;
98    /// use malachite_base::num::basic::integers::PrimitiveInt;
99    /// use malachite_base::num::basic::traits::Zero;
100    /// use malachite_nz::natural::Natural;
101    /// use malachite_nz::platform::Limb;
102    ///
103    /// if Limb::WIDTH == u32::WIDTH {
104    ///     assert_eq!(Natural::ZERO.limbs().next_back(), None);
105    ///
106    ///     // 10^12 = 232 * 2^32 + 3567587328
107    ///     let trillion = Natural::from(10u32).pow(12);
108    ///     let mut limbs = trillion.limbs();
109    ///     assert_eq!(limbs.next_back(), Some(232));
110    ///     assert_eq!(limbs.next_back(), Some(3567587328));
111    ///     assert_eq!(limbs.next_back(), None);
112    /// }
113    /// ```
114    fn next_back(&mut self) -> Option<Limb> {
115        if self.remaining != 0 {
116            let limb = match self.n {
117                Natural(Small(small)) => *small,
118                Natural(Large(limbs)) => limbs[usize::exact_from(self.j)],
119            };
120            if self.j != self.i {
121                self.j -= 1;
122            }
123            self.remaining -= 1;
124            Some(limb)
125        } else {
126            None
127        }
128    }
129}
130
131impl ExactSizeIterator for LimbIterator<'_> {}
132
133impl Index<usize> for LimbIterator<'_> {
134    type Output = Limb;
135
136    /// A function to retrieve a [`Natural`]'s [limbs](crate#limbs) by index.
137    ///
138    /// The index is the power of $2^W$ of which the limbs is a coefficient, where $W$ is the width
139    /// of a limb. Indexing at or above the limb count returns zeros.
140    ///
141    /// # Worst-case complexity
142    /// Constant time and additional memory.
143    ///
144    /// # Examples
145    /// ```
146    /// use malachite_base::num::arithmetic::traits::Pow;
147    /// use malachite_base::num::basic::integers::PrimitiveInt;
148    /// use malachite_base::num::basic::traits::Zero;
149    /// use malachite_nz::natural::Natural;
150    /// use malachite_nz::platform::Limb;
151    ///
152    /// if Limb::WIDTH == u32::WIDTH {
153    ///     assert_eq!(Natural::ZERO.limbs()[0], 0);
154    ///
155    ///     // 10^12 = 232 * 2^32 + 3567587328
156    ///     let trillion = Natural::from(10u32).pow(12);
157    ///     let limbs = trillion.limbs();
158    ///     assert_eq!(limbs[0], 3567587328);
159    ///     assert_eq!(limbs[1], 232);
160    ///     assert_eq!(limbs[2], 0);
161    ///     assert_eq!(limbs[100], 0);
162    /// }
163    /// ```
164    fn index(&self, index: usize) -> &Limb {
165        if index >= self.limb_count {
166            &0
167        } else {
168            match self.n {
169                Natural(Small(small)) => small,
170                Natural(Large(limbs)) => limbs.index(index),
171            }
172        }
173    }
174}
175
176impl LimbIterator<'_> {
177    // TODO document and test
178    #[allow(clippy::missing_const_for_fn)]
179    pub fn most_significant(&self) -> Option<Limb> {
180        match self.n {
181            Natural(Small(0)) => None,
182            Natural(Small(small)) => Some(*small),
183            Natural(Large(limbs)) => limbs.last().copied(),
184        }
185    }
186}
187
188impl Natural {
189    /// Returns the [limbs](crate#limbs) of a [`Natural`], in ascending order, so that
190    /// less-significant limbs have lower indices in the output vector.
191    ///
192    /// There are no trailing zero limbs.
193    ///
194    /// This function borrows the [`Natural`]. If taking ownership is possible instead,
195    /// [`into_limbs_asc`](Self::into_limbs_asc) is more efficient.
196    ///
197    /// This function is more efficient than [`to_limbs_desc`](Self::to_limbs_desc).
198    ///
199    /// # Worst-case complexity
200    /// $T(n) = O(n)$
201    ///
202    /// $M(n) = O(n)$
203    ///
204    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
205    ///
206    /// # Examples
207    /// ```
208    /// use malachite_base::num::arithmetic::traits::Pow;
209    /// use malachite_base::num::basic::integers::PrimitiveInt;
210    /// use malachite_base::num::basic::traits::Zero;
211    /// use malachite_nz::natural::Natural;
212    /// use malachite_nz::platform::Limb;
213    ///
214    /// if Limb::WIDTH == u32::WIDTH {
215    ///     assert!(Natural::ZERO.to_limbs_asc().is_empty());
216    ///     assert_eq!(Natural::from(123u32).to_limbs_asc(), &[123]);
217    ///     // 10^12 = 232 * 2^32 + 3567587328
218    ///     assert_eq!(
219    ///         Natural::from(10u32).pow(12).to_limbs_asc(),
220    ///         &[3567587328, 232]
221    ///     );
222    /// }
223    /// ```
224    pub fn to_limbs_asc(&self) -> Vec<Limb> {
225        match self {
226            &Self::ZERO => Vec::new(),
227            Self(Small(small)) => vec![*small],
228            Self(Large(limbs)) => limbs.clone(),
229        }
230    }
231
232    /// Returns the [limbs](crate#limbs) of a [`Natural`] in descending order, so that
233    /// less-significant limbs have higher indices in the output vector.
234    ///
235    /// There are no leading zero limbs.
236    ///
237    /// This function borrows the [`Natural`]. If taking ownership is possible instead,
238    /// [`into_limbs_desc`](Self::into_limbs_desc) is more efficient.
239    ///
240    /// This function is less efficient than [`to_limbs_asc`](Self::to_limbs_asc).
241    ///
242    /// # Worst-case complexity
243    /// $T(n) = O(n)$
244    ///
245    /// $M(n) = O(n)$
246    ///
247    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
248    ///
249    /// # Examples
250    /// ```
251    /// use malachite_base::num::arithmetic::traits::Pow;
252    /// use malachite_base::num::basic::integers::PrimitiveInt;
253    /// use malachite_base::num::basic::traits::Zero;
254    /// use malachite_nz::natural::Natural;
255    /// use malachite_nz::platform::Limb;
256    ///
257    /// if Limb::WIDTH == u32::WIDTH {
258    ///     assert!(Natural::ZERO.to_limbs_desc().is_empty());
259    ///     assert_eq!(Natural::from(123u32).to_limbs_desc(), &[123]);
260    ///     // 10^12 = 232 * 2^32 + 3567587328
261    ///     assert_eq!(
262    ///         Natural::from(10u32).pow(12).to_limbs_desc(),
263    ///         &[232, 3567587328]
264    ///     );
265    /// }
266    /// ```
267    pub fn to_limbs_desc(&self) -> Vec<Limb> {
268        match self {
269            &Self::ZERO => Vec::new(),
270            Self(Small(small)) => vec![*small],
271            Self(Large(limbs)) => limbs.iter().copied().rev().collect(),
272        }
273    }
274
275    /// Returns the [limbs](crate#limbs) of a [`Natural`], in ascending order, so that
276    /// less-significant limbs have lower indices in the output vector.
277    ///
278    /// There are no trailing zero limbs.
279    ///
280    /// This function takes ownership of the [`Natural`]. If it's necessary to borrow instead, use
281    /// [`to_limbs_asc`](Self::to_limbs_asc).
282    ///
283    /// This function is more efficient than [`into_limbs_desc`](Self::into_limbs_desc).
284    ///
285    /// # Worst-case complexity
286    /// Constant time and additional memory.
287    ///
288    /// # Examples
289    /// ```
290    /// use malachite_base::num::arithmetic::traits::Pow;
291    /// use malachite_base::num::basic::integers::PrimitiveInt;
292    /// use malachite_base::num::basic::traits::Zero;
293    /// use malachite_nz::natural::Natural;
294    /// use malachite_nz::platform::Limb;
295    ///
296    /// if Limb::WIDTH == u32::WIDTH {
297    ///     assert!(Natural::ZERO.into_limbs_asc().is_empty());
298    ///     assert_eq!(Natural::from(123u32).into_limbs_asc(), &[123]);
299    ///     // 10^12 = 232 * 2^32 + 3567587328
300    ///     assert_eq!(
301    ///         Natural::from(10u32).pow(12).into_limbs_asc(),
302    ///         &[3567587328, 232]
303    ///     );
304    /// }
305    /// ```
306    pub fn into_limbs_asc(self) -> Vec<Limb> {
307        match self {
308            Self::ZERO => Vec::new(),
309            Self(Small(small)) => vec![small],
310            Self(Large(limbs)) => limbs,
311        }
312    }
313
314    /// Returns the [limbs](crate#limbs) of a [`Natural`], in descending order, so that
315    /// less-significant limbs have higher indices in the output vector.
316    ///
317    /// There are no leading zero limbs.
318    ///
319    /// This function takes ownership of the [`Natural`]. If it's necessary to borrow instead, use
320    /// [`to_limbs_desc`](Self::to_limbs_desc).
321    ///
322    /// This function is less efficient than [`into_limbs_asc`](Self::into_limbs_asc).
323    ///
324    /// # Worst-case complexity
325    /// $T(n) = O(n)$
326    ///
327    /// $M(n) = O(1)$
328    ///
329    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
330    ///
331    /// # Examples
332    /// ```
333    /// use malachite_base::num::arithmetic::traits::Pow;
334    /// use malachite_base::num::basic::integers::PrimitiveInt;
335    /// use malachite_base::num::basic::traits::Zero;
336    /// use malachite_nz::natural::Natural;
337    /// use malachite_nz::platform::Limb;
338    ///
339    /// if Limb::WIDTH == u32::WIDTH {
340    ///     assert!(Natural::ZERO.into_limbs_desc().is_empty());
341    ///     assert_eq!(Natural::from(123u32).into_limbs_desc(), &[123]);
342    ///     // 10^12 = 232 * 2^32 + 3567587328
343    ///     assert_eq!(
344    ///         Natural::from(10u32).pow(12).into_limbs_desc(),
345    ///         &[232, 3567587328]
346    ///     );
347    /// }
348    /// ```
349    pub fn into_limbs_desc(self) -> Vec<Limb> {
350        match self {
351            Self::ZERO => Vec::new(),
352            Self(Small(small)) => vec![small],
353            Self(Large(mut limbs)) => {
354                limbs.reverse();
355                limbs
356            }
357        }
358    }
359
360    /// Returns the [limbs](crate#limbs) of a [`Natural`], in ascending order, so that
361    /// less-significant limbs have lower indices in the output slice.
362    ///
363    /// There are no trailing zero limbs.
364    ///
365    /// This function borrows the [`Natural`]. There is no descending order counterpoint, but
366    /// [`to_limbs_desc`](Self::to_limbs_desc) may be used instead.
367    ///
368    /// This function is more efficient than [`to_limbs_asc`](Self::to_limbs_asc) because it borrows
369    /// the underlying memory directly.
370    ///
371    /// # Worst-case complexity
372    /// Constant time and additional memory.
373    ///
374    /// # Examples
375    /// ```
376    /// use malachite_base::num::arithmetic::traits::Pow;
377    /// use malachite_base::num::basic::integers::PrimitiveInt;
378    /// use malachite_base::num::basic::traits::Zero;
379    /// use malachite_nz::natural::Natural;
380    /// use malachite_nz::platform::Limb;
381    ///
382    /// if Limb::WIDTH == u32::WIDTH {
383    ///     assert!(Natural::ZERO.as_limbs_asc().is_empty());
384    ///     assert_eq!(Natural::from(123u32).as_limbs_asc(), &[123]);
385    ///     // 10^12 = 232 * 2^32 + 3567587328
386    ///     assert_eq!(
387    ///         Natural::from(10u32).pow(12).as_limbs_asc(),
388    ///         &[3567587328, 232]
389    ///     );
390    /// }
391    /// ```
392    pub fn as_limbs_asc(&self) -> &[Limb] {
393        match self {
394            Self(Small(0)) => &[],
395            Self(Small(small)) => slice::from_ref(small),
396            Self(Large(limbs)) => limbs,
397        }
398    }
399
400    /// Returns a double-ended iterator over the [limbs](crate#limbs) of a [`Natural`].
401    ///
402    /// The forward order is ascending, so that less-significant limbs appear first. There are no
403    /// trailing zero limbs going forward, or leading zeros going backward.
404    ///
405    /// If it's necessary to get a [`Vec`] of all the limbs, consider using
406    /// [`to_limbs_asc`](Self::to_limbs_asc), [`to_limbs_desc`](Self::to_limbs_desc),
407    /// [`into_limbs_asc`](Self::into_limbs_asc), or [`into_limbs_desc`](Self::into_limbs_desc)
408    /// instead.
409    ///
410    /// # Worst-case complexity
411    /// Constant time and additional memory.
412    ///
413    /// # Examples
414    /// ```
415    /// use itertools::Itertools;
416    /// use malachite_base::num::arithmetic::traits::Pow;
417    /// use malachite_base::num::basic::integers::PrimitiveInt;
418    /// use malachite_base::num::basic::traits::Zero;
419    /// use malachite_nz::natural::Natural;
420    /// use malachite_nz::platform::Limb;
421    ///
422    /// if Limb::WIDTH == u32::WIDTH {
423    ///     assert!(Natural::ZERO.limbs().next().is_none());
424    ///     assert_eq!(Natural::from(123u32).limbs().collect_vec(), &[123]);
425    ///     // 10^12 = 232 * 2^32 + 3567587328
426    ///     assert_eq!(
427    ///         Natural::from(10u32).pow(12).limbs().collect_vec(),
428    ///         &[3567587328, 232]
429    ///     );
430    ///
431    ///     assert!(Natural::ZERO.limbs().next_back().is_none());
432    ///     assert_eq!(Natural::from(123u32).limbs().rev().collect_vec(), &[123]);
433    ///     // 10^12 = 232 * 2^32 + 3567587328
434    ///     assert_eq!(
435    ///         Natural::from(10u32).pow(12).limbs().rev().collect_vec(),
436    ///         &[232, 3567587328]
437    ///     );
438    /// }
439    /// ```
440    pub fn limbs(&self) -> LimbIterator<'_> {
441        let limb_count = self.limb_count();
442        let limb_count_usize = usize::exact_from(limb_count);
443        LimbIterator {
444            n: self,
445            limb_count: limb_count_usize,
446            remaining: limb_count_usize,
447            i: 0,
448            j: limb_count.saturating_sub(1),
449        }
450    }
451}