malachite_base/vector.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::num::conversion::traits::ExactFrom;
10use alloc::vec;
11use alloc::vec::Vec;
12use core::mem::take;
13
14/// What every vector type has in common: a vector of a fixed dimension, stored as its elements in
15/// order.
16///
17/// The functions here are the ones whose meaning does not depend on what the elements are. Each
18/// implementation documents its own complexity and gives its own examples.
19pub trait Vector: Sized {
20 /// The type of an element.
21 type Element;
22
23 /// What [`pivot`](Self::pivot) returns.
24 ///
25 /// This is a reference to an [`Element`](Self::Element) when the vector holds elements that are
26 /// expensive to copy, and an [`Element`](Self::Element) itself when one is cheap to copy.
27 type ElementOutput<'a>
28 where
29 Self: 'a;
30
31 /// Converts a slice to a vector, cloning the elements.
32 ///
33 /// The vector's dimension is the length of the slice. Every slice is a valid vector, so this
34 /// cannot fail; the empty slice gives the 0-dimensional vector.
35 fn from_elements(xs: &[Self::Element]) -> Self
36 where
37 Self::Element: Clone;
38
39 /// Converts a [`Vec`] to a vector, taking ownership of it.
40 ///
41 /// The vector's dimension is the length of the [`Vec`]. Every [`Vec`] is a valid vector, so
42 /// this cannot fail, and nothing is copied or allocated.
43 fn from_owned_elements(xs: Vec<Self::Element>) -> Self;
44
45 /// Returns the zero vector of a given dimension: a vector of `dimension` zeros.
46 fn zero(dimension: u64) -> Self;
47
48 /// Returns a standard basis vector: the vector of a given dimension whose element at `index` is
49 /// 1 and whose other elements are 0.
50 fn standard_basis_vector(dimension: u64, index: u64) -> Self;
51
52 /// Appends an element to the end of a vector, increasing its dimension by 1.
53 fn push(&mut self, x: Self::Element);
54
55 /// Sets the dimension of a vector, removing elements from the end if the new dimension is
56 /// smaller, and appending zeros if it is larger.
57 fn set_dimension(&mut self, dimension: u64);
58
59 /// Sets every element of a vector to zero, keeping its dimension.
60 fn set_zero(&mut self);
61
62 /// Sorts the elements of a vector in ascending order, keeping its dimension.
63 fn sort(&mut self);
64
65 /// Returns a vector's elements as a [`Vec`], cloning them.
66 fn to_elements(&self) -> Vec<Self::Element>
67 where
68 Self::Element: Clone;
69
70 /// Returns a vector's elements as a [`Vec`], taking ownership of the vector.
71 ///
72 /// The [`Vec`] is what [`from_owned_elements`](Self::from_owned_elements) would take back.
73 fn into_elements(self) -> Vec<Self::Element>;
74
75 /// Returns a reference to a vector's elements, as a slice.
76 fn elements_ref(&self) -> &[Self::Element];
77
78 /// Returns the dimension of a vector: the number of its elements.
79 fn dimension(&self) -> u64;
80
81 /// Determines whether every element of a vector is zero. This includes the 0-dimensional
82 /// vector, which has no elements.
83 fn is_zero(&self) -> bool;
84
85 /// Returns the pivot of a vector: its first nonzero element.
86 ///
87 /// This is the element that leads the vector when it is a row of a matrix in echelon form.
88 /// Returns `None` if every element is zero, which includes the 0-dimensional vector.
89 fn pivot(&self) -> Option<Self::ElementOutput<'_>>;
90
91 /// Returns the index of the pivot of a vector: the position of its first nonzero element.
92 ///
93 /// Indices start at 0, as they do for [`Index`](core::ops::Index). Returns `None` if every
94 /// element is zero, which includes the 0-dimensional vector. When it returns `Some(i)`,
95 /// [`pivot`](Self::pivot) is the element at `i`.
96 fn pivot_index(&self) -> Option<u64>;
97
98 /// Returns the index of an element of largest height: the first one, when several share it.
99 ///
100 /// The height of an integer is its absolute value, and the height of a rational number $p/q$ in
101 /// lowest terms is $\max(|p|, q)$. Returns `None` for the 0-dimensional vector.
102 fn height_index(&self) -> Option<u64>;
103
104 /// Determines whether a vector is a standard basis vector, returning the index of its 1 if it
105 /// is.
106 ///
107 /// A standard basis vector has a single element equal to 1 and every other element 0, as
108 /// [`standard_basis_vector`](Self::standard_basis_vector) builds. Returns `None` for every
109 /// other vector, including the zero vectors and the 0-dimensional vector. When it returns
110 /// `Some(i)`, `i` is also the [`pivot_index`](Self::pivot_index), and the vector equals
111 /// `standard_basis_vector(self.dimension(), i)`.
112 fn standard_basis_index(&self) -> Option<u64>;
113
114 /// Returns the number of significant bits of a vector's height, together with whether any of
115 /// its elements is negative.
116 ///
117 /// The bit count is the largest bit length of any element's height, or 0 for the 0-dimensional
118 /// vector; it is what `Height::height_significant_bits` returns.
119 fn max_bits(&self) -> (u64, bool);
120
121 /// Returns the number of significant bits of a vector's $\ell^1$ norm, the sum of the absolute
122 /// values of its elements, together with the number of significant bits of its height.
123 ///
124 /// The counts are what `L1Norm::l1_norm_significant_bits` and `Height::height_significant_bits`
125 /// return, computed together in one pass where possible. The height of the 0-dimensional vector
126 /// is 0, and so, for integer elements, is its norm.
127 fn sum_max_bits(&self) -> (u64, u64);
128}
129
130/// Selects coordinates of a vector by index: the result's element $j$ is the original's element
131/// `indices[j]`.
132///
133/// The indices may repeat and may appear in any order, so this covers projection onto some of the
134/// coordinates (strictly increasing indices), permutation, and duplication of coordinates. The
135/// result's dimension is the number of indices.
136pub trait SelectCoordinates {
137 type Output;
138
139 fn select_coordinates(self, indices: &[u64]) -> Self::Output;
140}
141
142/// Selects coordinates of a vector by index, in place: afterwards, element $j$ of the vector is
143/// what element `indices[j]` was before.
144pub trait SelectCoordinatesAssign {
145 fn select_coordinates_assign(&mut self, indices: &[u64]);
146}
147
148fn check_index(index: u64, dimension: usize) -> usize {
149 let index = usize::exact_from(index);
150 assert!(
151 index < dimension,
152 "index {index} is out of range for a vector of dimension {dimension}"
153 );
154 index
155}
156
157// The elements of `xs` at `indices`, cloned. Panics if an index is out of range.
158#[doc(hidden)]
159#[inline]
160pub fn select_elements<T: Clone>(xs: &[T], indices: &[u64]) -> Vec<T> {
161 indices
162 .iter()
163 .map(|&i| xs[check_index(i, xs.len())].clone())
164 .collect()
165}
166
167// Replaces `xs` with its elements at `indices`, cloning as few as possible. Panics if an index is
168// out of range.
169//
170// When the indices are strictly increasing, the selected elements are swapped into place and the
171// rest truncated away, so nothing is cloned or allocated. Otherwise each element is moved out at
172// its last use and cloned at any earlier one, so an element is cloned once for each extra time it
173// is selected, which is as few clones as any method needs.
174#[doc(hidden)]
175pub fn select_elements_in_place<T: Clone + Default>(xs: &mut Vec<T>, indices: &[u64]) {
176 let n = xs.len();
177 if indices.windows(2).all(|w| w[0] < w[1]) {
178 if let Some(&last) = indices.last() {
179 check_index(last, n);
180 }
181 for (j, &i) in indices.iter().enumerate() {
182 let i = usize::exact_from(i);
183 if i != j {
184 xs.swap(j, i);
185 }
186 }
187 xs.truncate(indices.len());
188 return;
189 }
190 let mut last_use = vec![usize::MAX; n];
191 for (j, &i) in indices.iter().enumerate() {
192 last_use[check_index(i, n)] = j;
193 }
194 let mut selected = Vec::with_capacity(indices.len());
195 for (j, &i) in indices.iter().enumerate() {
196 let i = usize::exact_from(i);
197 selected.push(if last_use[i] == j {
198 take(&mut xs[i])
199 } else {
200 xs[i].clone()
201 });
202 }
203 *xs = selected;
204}