malachite_base/slices/mod.rs
1// Copyright © 2025 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MP Library.
4//
5// Copyright © 1991, 1993-1997, 1999-2016, 2009, 2020 Free Software Foundation, Inc.
6//
7// This file is part of Malachite.
8//
9// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
10// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
11// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
12
13use crate::num::arithmetic::traits::DivisibleBy;
14use crate::num::basic::traits::Zero;
15#[cfg(feature = "random")]
16use crate::num::conversion::traits::ExactFrom;
17#[cfg(feature = "random")]
18use crate::num::random::{RandomUnsignedsLessThan, random_unsigneds_less_than};
19#[cfg(feature = "random")]
20use crate::random::Seed;
21use alloc::vec::Vec;
22#[cfg(feature = "random")]
23use rand::prelude::SliceRandom;
24#[cfg(feature = "random")]
25use rand_chacha::ChaCha20Rng;
26
27/// Sets all values in a slice to 0.
28///
29/// # Worst-case complexity
30/// $T(n) = O(n)$
31///
32/// $M(n) = O(1)$
33///
34/// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
35///
36/// # Examples
37/// ```
38/// use malachite_base::slices::slice_set_zero;
39///
40/// let mut xs = [1, 2, 3, 4, 5];
41/// slice_set_zero::<u32>(&mut xs[1..4]);
42/// assert_eq!(xs, [1, 0, 0, 0, 5]);
43/// ```
44///
45/// This is equivalent to `mpn_zero` from `mpn/generic/zero.c`, GMP 6.2.1. Note that this is needed
46/// less often in Malachite than in GMP, since Malachite generally initializes new memory with
47/// zeros.
48pub fn slice_set_zero<T: Zero>(xs: &mut [T]) {
49 for x in &mut *xs {
50 *x = T::ZERO;
51 }
52}
53
54/// Tests whether all values in a slice are equal to 0.
55///
56/// # Worst-case complexity
57/// $T(n) = O(n)$
58///
59/// $M(n) = O(1)$
60///
61/// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
62///
63/// # Examples
64/// ```
65/// use malachite_base::slices::slice_test_zero;
66///
67/// assert!(slice_test_zero::<u32>(&[0, 0, 0]));
68/// assert!(!slice_test_zero::<u32>(&[0, 1, 0]));
69/// ```
70///
71/// This is equivalent to `mpn_zero_p` from `gmp-h.in`, GMP 6.2.1.
72pub fn slice_test_zero<T: Eq + Zero>(xs: &[T]) -> bool {
73 let zero = T::ZERO;
74 xs.iter().all(|x| x == &zero)
75}
76
77/// Counts the number of zeros that a slice starts with.
78///
79/// # Worst-case complexity
80/// $T(n) = O(n)$
81///
82/// $M(n) = O(1)$
83///
84/// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
85///
86/// # Examples
87/// ```
88/// use malachite_base::slices::slice_leading_zeros;
89///
90/// assert_eq!(slice_leading_zeros::<u32>(&[1, 2, 3]), 0);
91/// assert_eq!(slice_leading_zeros::<u32>(&[0, 0, 0, 1, 2, 3]), 3);
92/// ```
93pub fn slice_leading_zeros<T: Eq + Zero>(xs: &[T]) -> usize {
94 let zero = T::ZERO;
95 xs.iter().take_while(|&x| x == &zero).count()
96}
97
98/// Counts the number of zeros that a slice ends with.
99///
100/// # Worst-case complexity
101/// $T(n) = O(n)$
102///
103/// $M(n) = O(1)$
104///
105/// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
106///
107/// # Examples
108/// ```
109/// use malachite_base::slices::slice_trailing_zeros;
110///
111/// assert_eq!(slice_trailing_zeros::<u32>(&[1, 2, 3]), 0);
112/// assert_eq!(slice_trailing_zeros::<u32>(&[1, 2, 3, 0, 0, 0]), 3);
113/// ```
114pub fn slice_trailing_zeros<T: Eq + Zero>(xs: &[T]) -> usize {
115 let zero = T::ZERO;
116 xs.iter().rev().take_while(|&x| x == &zero).count()
117}
118
119/// Given a slice and an starting index, copies the subslice starting from that index to the
120/// beginning of the slice.
121///
122/// In other words, this function copies the contents of `&xs[starting_index..]` to `&xs[..xs.len()
123/// - starting_index]`.
124///
125/// In other other words, if $k$ is `starting_index`, the sequence $[x_0, x_1, \ldots, x_{n-1}]$
126/// becomes $[x_k, x_{k+1}, \ldots, x_{n-1}, x_{n-k}, x_{n-k+1}, \ldots, x_{n-1}]$.
127///
128/// If `starting_index` is zero or `xs.len()`, nothing happens.
129///
130/// # Worst-case complexity
131/// $T(n) = O(n)$
132///
133/// $M(n) = O(1)$
134///
135/// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
136///
137/// # Panics
138/// Panics if `starting_index` is greater than the length of `xs`.
139///
140/// # Examples
141/// ```
142/// use malachite_base::slices::slice_move_left;
143///
144/// let xs = &mut [1, 2, 3, 4, 5, 6];
145/// slice_move_left::<u32>(xs, 2);
146/// assert_eq!(xs, &[3, 4, 5, 6, 5, 6]);
147/// ```
148#[inline]
149pub fn slice_move_left<T: Copy>(xs: &mut [T], starting_index: usize) {
150 xs.copy_within(starting_index..xs.len(), 0);
151}
152
153/// Splits an immutable slice into adjacent immutable chunks.
154///
155/// An input slice $\mathbf{x}$, a chunk length $n$, and $k + 1$ output slice names $\\mathbf{x}_0,
156/// \\mathbf{x}_1, \\ldots, \\mathbf{x}_k$ are given. The last output slice name, $\mathbf{x}_k$, is
157/// specified via a separate argument called `xs_last`.
158///
159/// The first $k$ output slice names are assigned adjacent length-$n$ chunks from $\mathbf{x}$. If
160/// $|\mathbf{x}| < kn$, the generated code panics.
161///
162/// The last slice, $\mathbf{x}_k$, which is assigned to `xs_last`, has length $|\mathbf{x}| - kn$.
163/// This length may be greater than $n$.
164///
165/// # Worst-case complexity
166/// $T(k) = O(k)$
167///
168/// $M(k) = O(1)$
169///
170/// where $T$ is time, $M$ is additional memory, and $k$ is the number of output slice names `xs_i`.
171///
172/// # Examples
173/// ```
174/// use malachite_base::split_into_chunks;
175///
176/// let xs = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
177/// split_into_chunks!(xs, 3, [xs_1, xs_2, xs_3], xs_4);
178/// assert_eq!(xs_1, &[0, 1, 2]);
179/// assert_eq!(xs_2, &[3, 4, 5]);
180/// assert_eq!(xs_3, &[6, 7, 8]);
181/// assert_eq!(xs_4, &[9, 10, 11, 12]);
182/// ```
183#[macro_export]
184macro_rules! split_into_chunks {
185 ($xs: expr, $n: expr, [$($xs_i: ident),*], $xs_last: ident) => {
186 let remainder = &$xs[..];
187 let n = $n;
188 $(
189 let ($xs_i, remainder) = remainder.split_at(n);
190 )*
191 let $xs_last = remainder;
192 }
193}
194
195/// Splits a mutable slice into adjacent mutable chunks.
196///
197/// An input slice $\mathbf{x}$, a chunk length $n$, and $k + 1$ output slice names $\\mathbf{x}_0,
198/// \\mathbf{x}_1, \\ldots, \\mathbf{x}_k$ are given. The last output slice name, $\mathbf{x}_k$, is
199/// specified via a separate argument called `xs_last`.
200///
201/// The first $k$ output slice names are assigned adjacent length-$n$ chunks from $\mathbf{x}$. If
202/// $|\mathbf{x}| < kn$, the generated code panics.
203///
204/// The last slice, $\mathbf{x}_k$, which is assigned to `xs_last`, has length $|\mathbf{x}| - kn$.
205/// This length may be greater than $n$.
206///
207/// # Worst-case complexity
208/// $T(k) = O(k)$
209///
210/// $M(k) = O(1)$
211///
212/// where $T$ is time, $M$ is additional memory, and $k$ is the number of output slice names `xs_i`.
213///
214/// # Examples
215/// ```
216/// use malachite_base::slices::slice_set_zero;
217/// use malachite_base::split_into_chunks_mut;
218///
219/// let xs = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
220/// split_into_chunks_mut!(xs, 3, [xs_1, xs_2, xs_3], xs_4);
221/// assert_eq!(xs_1, &[0, 1, 2]);
222/// assert_eq!(xs_2, &[3, 4, 5]);
223/// assert_eq!(xs_3, &[6, 7, 8]);
224/// assert_eq!(xs_4, &[9, 10, 11, 12]);
225///
226/// slice_set_zero(xs_2);
227/// assert_eq!(xs, &[0, 1, 2, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12]);
228/// ```
229#[macro_export]
230macro_rules! split_into_chunks_mut {
231 ($xs: expr, $n: expr, [$($xs_i: ident),*], $xs_last: ident) => {
232 let remainder = &mut $xs[..];
233 let n = $n;
234 $(
235 let ($xs_i, remainder) = remainder.split_at_mut(n);
236 )*
237 let $xs_last = remainder;
238 }
239}
240
241#[cfg(feature = "random")]
242/// Uniformly generates a random reference to a value from a nonempty slice.
243///
244/// This `struct` is created by [`random_values_from_slice`]; see its documentation for more.
245#[derive(Clone, Debug)]
246pub struct RandomValuesFromSlice<'a, T> {
247 xs: &'a [T],
248 indices: RandomUnsignedsLessThan<u64>,
249}
250
251#[cfg(feature = "random")]
252impl<'a, T> Iterator for RandomValuesFromSlice<'a, T> {
253 type Item = &'a T;
254
255 #[inline]
256 fn next(&mut self) -> Option<&'a T> {
257 Some(&self.xs[usize::exact_from(self.indices.next().unwrap())])
258 }
259}
260
261#[cfg(feature = "random")]
262/// Uniformly generates a random reference to a value from a nonempty slice.
263///
264/// The iterator cannot outlive the slice. It may be more convenient for the iterator to own the
265/// data, in which case you may use [`random_values_from_vec`](crate::vecs::random_values_from_vec)
266/// instead.
267///
268/// The output length is infinite.
269///
270/// $P(x) = 1/n$, where $n$ is `xs.len()`.
271///
272/// # Expected complexity per iteration
273/// Constant time and additional memory.
274///
275/// # Panics
276/// Panics if `xs` is empty.
277///
278/// # Examples
279/// ```
280/// use itertools::Itertools;
281/// use malachite_base::random::EXAMPLE_SEED;
282/// use malachite_base::slices::random_values_from_slice;
283///
284/// let xs = &[2, 3, 5, 7, 11];
285/// assert_eq!(
286/// random_values_from_slice(EXAMPLE_SEED, xs)
287/// .cloned()
288/// .take(10)
289/// .collect_vec(),
290/// &[3, 7, 3, 5, 11, 3, 5, 11, 2, 2]
291/// );
292/// ```
293#[inline]
294pub fn random_values_from_slice<T>(seed: Seed, xs: &[T]) -> RandomValuesFromSlice<T> {
295 assert!(!xs.is_empty(), "empty slice");
296 RandomValuesFromSlice {
297 xs,
298 indices: random_unsigneds_less_than(seed, u64::exact_from(xs.len())),
299 }
300}
301
302pub(crate) fn advance_indices(indices: &mut [usize]) -> bool {
303 let n = indices.len();
304 if n == 0 {
305 return true;
306 }
307 // Find the index of the value right before the longest descending suffix.
308 let mut pivot_index = n;
309 let mut i = 0;
310 let mut reached_end = true;
311 while pivot_index > 0 {
312 pivot_index -= 1;
313 let next_i = indices[pivot_index];
314 if next_i < i {
315 reached_end = false;
316 break;
317 }
318 i = next_i;
319 }
320 if reached_end {
321 return true;
322 }
323 let pivot = indices[pivot_index];
324 let mut swap_index = n - 1;
325 while indices[swap_index] < pivot {
326 swap_index -= 1;
327 }
328 indices.swap(pivot_index, swap_index);
329 indices[pivot_index + 1..].reverse();
330 false
331}
332
333/// Generates every permutation of a slice.
334///
335/// This `struct` is created by [`exhaustive_slice_permutations`]; see its documentation for more.
336#[derive(Clone, Debug, Eq, Hash, PartialEq)]
337pub struct ExhaustiveSlicePermutations<'a, T> {
338 xs: &'a [T],
339 indices: Vec<usize>,
340 done: bool,
341}
342
343impl<'a, T> Iterator for ExhaustiveSlicePermutations<'a, T> {
344 type Item = Vec<&'a T>;
345
346 fn next(&mut self) -> Option<Vec<&'a T>> {
347 if self.done {
348 None
349 } else {
350 let out = Some(self.indices.iter().map(|&i| &self.xs[i]).collect());
351 self.done = advance_indices(&mut self.indices);
352 out
353 }
354 }
355}
356
357/// Generates every permutation of a slice.
358///
359/// The permutations are [`Vec`]s of references into the slice. It may be more convenient for the
360/// iterator to own the data, in which case you may use
361/// [`exhaustive_vec_permutations`](crate::vecs::exhaustive_vec_permutations) instead.
362///
363/// The permutations are generated in lexicographic order with respect to the ordering in the slice.
364///
365/// The output length is $n!$, where $n$ is `xs.len()`.
366///
367/// # Expected complexity per iteration
368/// $T(n) = O(n)$
369///
370/// $M(n) = O(n)$
371///
372/// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
373///
374/// # Examples
375/// ```
376/// use itertools::Itertools;
377/// use malachite_base::slices::exhaustive_slice_permutations;
378///
379/// let css: Vec<String> = exhaustive_slice_permutations(&['a', 'b', 'c', 'd'])
380/// .map(|ds| ds.into_iter().copied().collect())
381/// .collect();
382/// assert_eq!(
383/// css.iter().map(String::as_str).collect_vec().as_slice(),
384/// [
385/// "abcd", "abdc", "acbd", "acdb", "adbc", "adcb", "bacd", "badc", "bcad", "bcda", "bdac",
386/// "bdca", "cabd", "cadb", "cbad", "cbda", "cdab", "cdba", "dabc", "dacb", "dbac", "dbca",
387/// "dcab", "dcba"
388/// ]
389/// );
390/// ```
391pub fn exhaustive_slice_permutations<T>(xs: &[T]) -> ExhaustiveSlicePermutations<T> {
392 ExhaustiveSlicePermutations {
393 xs,
394 indices: (0..xs.len()).collect(),
395 done: false,
396 }
397}
398
399#[cfg(feature = "random")]
400/// Uniformly generates a random permutation of references to a slice.
401///
402/// This `struct` is created by [`random_slice_permutations`]; see its documentation for more.
403#[derive(Clone, Debug)]
404pub struct RandomSlicePermutations<'a, T> {
405 xs: &'a [T],
406 indices: Vec<usize>,
407 rng: ChaCha20Rng,
408}
409
410#[cfg(feature = "random")]
411impl<'a, T> Iterator for RandomSlicePermutations<'a, T> {
412 type Item = Vec<&'a T>;
413
414 fn next(&mut self) -> Option<Vec<&'a T>> {
415 self.indices.shuffle(&mut self.rng);
416 Some(self.indices.iter().map(|&i| &self.xs[i]).collect())
417 }
418}
419
420#[cfg(feature = "random")]
421/// Uniformly generates a random permutation of references to a slice.
422///
423/// The iterator cannot outlive the slice. It may be more convenient for the iterator to own the
424/// data, in which case you may use
425/// [`random_vec_permutations`](crate::vecs::random_vec_permutations) instead.
426///
427/// The output length is infinite.
428///
429/// $P(p) = 1/n!$, where $n$ is `xs.len()`.
430///
431/// # Expected complexity per iteration
432/// $T(n) = O(n)$
433///
434/// $M(n) = O(n)$
435///
436/// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
437///
438/// # Examples
439/// ```
440/// use itertools::Itertools;
441/// use malachite_base::random::EXAMPLE_SEED;
442/// use malachite_base::slices::random_slice_permutations;
443///
444/// let css: Vec<String> = random_slice_permutations(EXAMPLE_SEED, &['a', 'b', 'c', 'd'])
445/// .take(20)
446/// .map(|ds| ds.into_iter().copied().collect())
447/// .collect();
448/// assert_eq!(
449/// css.iter().map(String::as_str).collect_vec().as_slice(),
450/// [
451/// "cadb", "cbad", "cadb", "badc", "acdb", "cbad", "dabc", "dbca", "cdba", "cdab", "bacd",
452/// "cabd", "adbc", "cdab", "dcab", "abcd", "abcd", "dacb", "bcad", "adcb"
453/// ]
454/// );
455/// ```
456pub fn random_slice_permutations<T>(seed: Seed, xs: &[T]) -> RandomSlicePermutations<T> {
457 RandomSlicePermutations {
458 xs,
459 indices: (0..xs.len()).collect(),
460 rng: seed.get_rng(),
461 }
462}
463
464/// Given a slice with nonzero length $\ell$, returns the smallest $n$ such that the slice consists
465/// of $n/\ell$ copies of a length-$\ell$ subslice.
466///
467/// Typically $\ell = n$.
468///
469/// # Worst-case complexity
470/// $T(n) = O(n^{1+\varepsilon})$ for all $\varepsilon > 0$
471///
472/// $M(n) = O(n)$
473///
474/// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
475///
476/// # Panics
477/// Panics if `xs` is empty.
478///
479/// # Examples
480/// ```
481/// use malachite_base::slices::min_repeating_len;
482///
483/// assert_eq!(min_repeating_len(&[1, 2, 1, 2, 1, 2]), 2);
484/// assert_eq!(min_repeating_len(&[1, 2, 1, 2, 1, 3]), 6);
485/// assert_eq!(min_repeating_len(&[5, 5, 5]), 1);
486/// ```
487pub fn min_repeating_len<T: Eq>(xs: &[T]) -> usize {
488 let len = xs.len();
489 assert_ne!(len, 0);
490 for start_i in 1..=len >> 1 {
491 if !len.divisible_by(start_i) {
492 continue;
493 }
494 let (xs_lo, xs_hi) = xs.split_at(start_i);
495 if Iterator::eq(xs_lo.iter().cycle().take(len - start_i), xs_hi.iter()) {
496 return start_i;
497 }
498 }
499 len
500}