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}