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