Skip to main content

malachite_q/rational_vector/
mod.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::Rational;
10use alloc::vec;
11use alloc::vec::Vec;
12use core::ops::Deref;
13use malachite_base::named::Named;
14use malachite_base::num::arithmetic::traits::{Height, HeightRef, L1Norm};
15use malachite_base::num::basic::traits::{One, Zero};
16use malachite_base::num::conversion::traits::ExactFrom;
17use malachite_base::vector::Vector;
18use malachite_nz::natural::Natural;
19
20/// Implementations of [`Index`](core::ops::Index) and [`IndexMut`](core::ops::IndexMut) for
21/// [`RationalVector`].
22pub mod access;
23/// Traits for arithmetic on [`RationalVector`]s.
24pub mod arithmetic;
25/// Implementations of [`Ord`] and [`PartialOrd`] for [`ShortlexRationalVector`] and
26/// [`ShortlexRationalVectorRef`], comparing two vectors by dimension and then lexicographically.
27pub mod comparison;
28/// Functions for converting a [`RationalVector`] to and from other types.
29pub mod conversion;
30/// Iterators that generate [`RationalVector`]s without repetition.
31pub mod exhaustive;
32/// An implementation of [`Extend`], for appending the elements produced by an iterator to a
33/// [`RationalVector`].
34pub mod extend;
35/// Traits for logic and bit manipulation on [`RationalVector`]s.
36pub mod logic;
37/// Iterators that generate [`RationalVector`]s randomly.
38#[cfg(feature = "random")]
39pub mod random;
40/// Implementations of [`SelectCoordinates`](malachite_base::vector::SelectCoordinates) and
41/// [`SelectCoordinatesAssign`](malachite_base::vector::SelectCoordinatesAssign), for selecting
42/// coordinates of a [`RationalVector`] by index.
43pub mod select_coordinates;
44
45// The height of the 0-dimensional vector, which `height_ref` lends. A `Natural` owns a `Vec` when
46// it is large, so it has a destructor, and a reference to a constant with a destructor cannot be
47// promoted to `'static`; a `static` can be borrowed for as long as needed.
48pub(crate) static ZERO: Natural = Natural::ZERO;
49
50/// A vector whose elements are [`Rational`]s.
51///
52/// Its dimension is the number of elements, and the 0-dimensional vector has none. The field is
53/// public, since every [`Vec`] of [`Rational`]s is a valid vector: unlike a polynomial, a vector
54/// has no normal form to maintain, and two vectors are equal exactly when their elements are.
55///
56/// The elements are held entrywise, each as a [`Rational`] of its own. This is the representation
57/// FLINT uses for its `fmpq_vec` and `fmpq_mat`, rather than the single common denominator of a
58/// [`RationalPolynomial`](crate::rational_polynomial::RationalPolynomial): a vector's elements are
59/// read and written one at a time, and a common denominator would make every element as large as
60/// the least common multiple of all their denominators.
61/// [`to_numerators_and_denominator`](RationalVector::to_numerators_and_denominator) gives the
62/// common-denominator form when it is wanted.
63///
64/// A `RationalVector` is serialized as the list of its elements, each serialized the way a
65/// [`Rational`] is.
66///
67/// # Examples
68/// ```
69/// use malachite_base::num::basic::traits::{One, Two};
70/// use malachite_base::vector::Vector;
71/// use malachite_q::Rational;
72/// use malachite_q::rational_vector::RationalVector;
73///
74/// let v = RationalVector {
75///     elements: vec![Rational::ONE, Rational::TWO, Rational::from(3u32)],
76/// };
77/// assert_eq!(v.dimension(), 3);
78/// ```
79#[derive(Clone, Eq, Hash, PartialEq)]
80#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
81#[cfg_attr(feature = "serde", serde(transparent))]
82pub struct RationalVector {
83    pub elements: Vec<Rational>,
84}
85
86impl Vector for RationalVector {
87    type Element = Rational;
88    type ElementOutput<'a>
89        = &'a Rational
90    where
91        Self: 'a;
92
93    /// Converts a slice of [`Rational`]s to a [`RationalVector`], cloning them.
94    ///
95    /// The vector's dimension is the length of the slice. Every slice is a valid vector, so this
96    /// cannot fail; the empty slice gives the 0-dimensional vector.
97    ///
98    /// # Worst-case complexity
99    /// $T(n) = O(n)$
100    ///
101    /// $M(n) = O(n)$
102    ///
103    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
104    /// elements.
105    ///
106    /// # Examples
107    /// ```
108    /// use malachite_base::num::basic::traits::{One, Two};
109    /// use malachite_base::vector::Vector;
110    /// use malachite_q::Rational;
111    /// use malachite_q::rational_vector::RationalVector;
112    ///
113    /// assert_eq!(
114    ///     RationalVector::from_elements(&[Rational::ONE, Rational::TWO]).to_string(),
115    ///     "(1, 2)"
116    /// );
117    /// assert_eq!(RationalVector::from_elements(&[]).to_string(), "()");
118    /// ```
119    #[inline]
120    fn from_elements(xs: &[Rational]) -> Self {
121        Self {
122            elements: xs.to_vec(),
123        }
124    }
125
126    /// Converts a [`Vec`] of [`Rational`]s to a [`RationalVector`], taking ownership of it.
127    ///
128    /// The vector's dimension is the length of the [`Vec`]. Every [`Vec`] is a valid vector, so
129    /// this cannot fail, and nothing is copied or allocated.
130    ///
131    /// # Worst-case complexity
132    /// Constant time and additional memory.
133    ///
134    /// # Examples
135    /// ```
136    /// use malachite_base::num::basic::traits::{One, Two};
137    /// use malachite_base::vector::Vector;
138    /// use malachite_q::Rational;
139    /// use malachite_q::rational_vector::RationalVector;
140    ///
141    /// assert_eq!(
142    ///     RationalVector::from_owned_elements(vec![Rational::ONE, Rational::TWO]).to_string(),
143    ///     "(1, 2)"
144    /// );
145    /// assert_eq!(
146    ///     RationalVector::from_owned_elements(Vec::new()).to_string(),
147    ///     "()"
148    /// );
149    /// ```
150    #[inline]
151    fn from_owned_elements(xs: Vec<Rational>) -> Self {
152        Self { elements: xs }
153    }
154
155    /// Returns the zero vector of a given dimension: a vector of `dimension` zeros.
156    ///
157    /// # Worst-case complexity
158    /// $T(n) = O(n)$
159    ///
160    /// $M(n) = O(n)$
161    ///
162    /// where $T$ is time, $M$ is additional memory, and $n$ is `dimension`.
163    ///
164    /// # Panics
165    /// Panics if `dimension` is greater than [`usize::MAX`].
166    ///
167    /// # Examples
168    /// ```
169    /// use malachite_base::vector::Vector;
170    /// use malachite_q::rational_vector::RationalVector;
171    ///
172    /// assert_eq!(RationalVector::zero(3).to_string(), "(0, 0, 0)");
173    /// assert_eq!(RationalVector::zero(0).to_string(), "()");
174    /// ```
175    ///
176    /// This is equivalent to `_fmpq_vec_init` from `fmpq_vec/init.c`, FLINT 3.6.0.
177    #[inline]
178    fn zero(dimension: u64) -> Self {
179        Self {
180            elements: vec![Rational::ZERO; usize::exact_from(dimension)],
181        }
182    }
183
184    /// Returns the standard basis vector $e_i$ of a given dimension: the vector whose element at
185    /// `index` is 1 and whose other elements are 0.
186    ///
187    /// Indices start at 0, as they do for [`Index`](core::ops::Index).
188    ///
189    /// # Worst-case complexity
190    /// $T(n) = O(n)$
191    ///
192    /// $M(n) = O(n)$
193    ///
194    /// where $T$ is time, $M$ is additional memory, and $n$ is `dimension`.
195    ///
196    /// # Panics
197    /// Panics if `index` is greater than or equal to `dimension`, or if `dimension` is greater than
198    /// [`usize::MAX`].
199    ///
200    /// # Examples
201    /// ```
202    /// use malachite_base::vector::Vector;
203    /// use malachite_q::rational_vector::RationalVector;
204    ///
205    /// assert_eq!(
206    ///     RationalVector::standard_basis_vector(3, 1).to_string(),
207    ///     "(0, 1, 0)"
208    /// );
209    /// assert_eq!(
210    ///     RationalVector::standard_basis_vector(1, 0).to_string(),
211    ///     "(1)"
212    /// );
213    /// ```
214    fn standard_basis_vector(dimension: u64, index: u64) -> Self {
215        assert!(
216            index < dimension,
217            "the index {index} is not less than the dimension {dimension}"
218        );
219        let mut v = Self::zero(dimension);
220        v.elements[usize::exact_from(index)] = Rational::ONE;
221        v
222    }
223
224    /// Appends an element to the end of a [`RationalVector`], increasing its dimension by 1.
225    ///
226    /// # Worst-case complexity
227    /// $T(n) = O(n)$
228    ///
229    /// $M(n) = O(n)$
230    ///
231    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`. The capacity
232    /// grows geometrically, so pushing $n$ elements onto an empty vector takes $O(n)$ time in
233    /// total.
234    ///
235    /// # Examples
236    /// ```
237    /// use core::str::FromStr;
238    /// use malachite_base::vector::Vector;
239    /// use malachite_q::Rational;
240    /// use malachite_q::rational_vector::RationalVector;
241    ///
242    /// let mut v = RationalVector::from_str("(1, 2)").unwrap();
243    /// v.push(Rational::from_unsigneds(1u32, 3));
244    /// assert_eq!(v.to_string(), "(1, 2, 1/3)");
245    ///
246    /// let mut v = RationalVector::zero(0);
247    /// v.push(Rational::from(5));
248    /// assert_eq!(v.to_string(), "(5)");
249    /// ```
250    #[inline]
251    fn push(&mut self, x: Rational) {
252        self.elements.push(x);
253    }
254
255    /// Sets the dimension of a [`RationalVector`], removing elements from the end if the new
256    /// dimension is smaller, and appending zeros if it is larger.
257    ///
258    /// Reducing the dimension keeps the first `dimension` coordinates: it is the projection onto
259    /// them.
260    ///
261    /// # Worst-case complexity
262    /// $T(n) = O(n)$
263    ///
264    /// $M(n) = O(n)$
265    ///
266    /// where $T$ is time, $M$ is additional memory, and $n$ is the larger of `self.dimension()` and
267    /// `dimension`.
268    ///
269    /// # Panics
270    /// Panics if `dimension` is greater than [`usize::MAX`].
271    ///
272    /// # Examples
273    /// ```
274    /// use core::str::FromStr;
275    /// use malachite_base::vector::Vector;
276    /// use malachite_q::rational_vector::RationalVector;
277    ///
278    /// let mut v = RationalVector::from_str("(1, 2, 3)").unwrap();
279    /// v.set_dimension(5);
280    /// assert_eq!(v.to_string(), "(1, 2, 3, 0, 0)");
281    /// v.set_dimension(2);
282    /// assert_eq!(v.to_string(), "(1, 2)");
283    /// v.set_dimension(0);
284    /// assert_eq!(v.to_string(), "()");
285    /// ```
286    #[inline]
287    fn set_dimension(&mut self, dimension: u64) {
288        self.elements
289            .resize(usize::exact_from(dimension), Rational::ZERO);
290    }
291
292    /// Sets every element of a [`RationalVector`] to zero, keeping its dimension.
293    ///
294    /// Afterwards the vector equals [`zero`](Vector::zero) of the same dimension.
295    ///
296    /// # Worst-case complexity
297    /// $T(n) = O(n)$
298    ///
299    /// $M(n) = O(1)$
300    ///
301    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`.
302    ///
303    /// # Examples
304    /// ```
305    /// use core::str::FromStr;
306    /// use malachite_base::vector::Vector;
307    /// use malachite_q::rational_vector::RationalVector;
308    ///
309    /// let mut v = RationalVector::from_str("(1/2, -2, 3)").unwrap();
310    /// v.set_zero();
311    /// assert_eq!(v.to_string(), "(0, 0, 0)");
312    ///
313    /// let mut v = RationalVector::from_str("()").unwrap();
314    /// v.set_zero();
315    /// assert_eq!(v.to_string(), "()");
316    /// ```
317    #[inline]
318    fn set_zero(&mut self) {
319        self.elements.fill(Rational::ZERO);
320    }
321
322    /// Sorts the elements of a [`RationalVector`] in ascending order, keeping its dimension.
323    ///
324    /// Equal elements are indistinguishable, so the sort does not need to be stable, and an
325    /// unstable sort is used.
326    ///
327    /// # Worst-case complexity
328    /// $T(n) = O(n \log n)$
329    ///
330    /// $M(n) = O(1)$
331    ///
332    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`, assuming that
333    /// comparing two elements takes constant time; comparing large elements takes time proportional
334    /// to their sizes.
335    ///
336    /// # Examples
337    /// ```
338    /// use core::str::FromStr;
339    /// use malachite_base::vector::Vector;
340    /// use malachite_q::rational_vector::RationalVector;
341    ///
342    /// let mut v = RationalVector::from_str("(1/2, -1, 1/3, 0)").unwrap();
343    /// v.sort();
344    /// assert_eq!(v.to_string(), "(-1, 0, 1/3, 1/2)");
345    /// ```
346    ///
347    /// This is equivalent to `_fmpq_vec_sort` from `fmpq_vec/sort.c`, FLINT 3.6.0.
348    #[inline]
349    fn sort(&mut self) {
350        self.elements.sort_unstable();
351    }
352
353    /// Returns a [`RationalVector`]'s elements as a [`Vec`], cloning them.
354    ///
355    /// # Worst-case complexity
356    /// $T(n) = O(n)$
357    ///
358    /// $M(n) = O(n)$
359    ///
360    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
361    /// elements.
362    ///
363    /// # Examples
364    /// ```
365    /// use core::str::FromStr;
366    /// use malachite_base::strings::ToDebugString;
367    /// use malachite_base::vector::Vector;
368    /// use malachite_q::rational_vector::RationalVector;
369    ///
370    /// let v = RationalVector::from_str("(1, 2, 3)").unwrap();
371    /// assert_eq!(v.to_elements().to_debug_string(), "[1, 2, 3]");
372    /// assert_eq!(
373    ///     RationalVector::from_str("()")
374    ///         .unwrap()
375    ///         .to_elements()
376    ///         .to_debug_string(),
377    ///     "[]"
378    /// );
379    /// ```
380    #[inline]
381    fn to_elements(&self) -> Vec<Rational> {
382        self.elements.clone()
383    }
384
385    /// Returns a [`RationalVector`]'s elements as a [`Vec`], taking ownership of the
386    /// [`RationalVector`].
387    ///
388    /// Nothing is copied or allocated.
389    ///
390    /// # Worst-case complexity
391    /// Constant time and additional memory.
392    ///
393    /// # Examples
394    /// ```
395    /// use core::str::FromStr;
396    /// use malachite_base::strings::ToDebugString;
397    /// use malachite_base::vector::Vector;
398    /// use malachite_q::rational_vector::RationalVector;
399    ///
400    /// let v = RationalVector::from_str("(1, 2, 3)").unwrap();
401    /// assert_eq!(v.into_elements().to_debug_string(), "[1, 2, 3]");
402    /// assert_eq!(
403    ///     RationalVector::from_str("()")
404    ///         .unwrap()
405    ///         .into_elements()
406    ///         .to_debug_string(),
407    ///     "[]"
408    /// );
409    /// ```
410    #[inline]
411    fn into_elements(self) -> Vec<Rational> {
412        self.elements
413    }
414
415    /// Returns a reference to a [`RationalVector`]'s elements, as a slice.
416    ///
417    /// # Worst-case complexity
418    /// Constant time and additional memory.
419    ///
420    /// # Examples
421    /// ```
422    /// use core::str::FromStr;
423    /// use malachite_base::strings::ToDebugString;
424    /// use malachite_base::vector::Vector;
425    /// use malachite_q::rational_vector::RationalVector;
426    ///
427    /// let v = RationalVector::from_str("(1, 2, 3)").unwrap();
428    /// assert_eq!(v.elements_ref().to_debug_string(), "[1, 2, 3]");
429    ///
430    /// // A slice of the elements can be taken directly.
431    /// let tail = &v.elements_ref()[1..];
432    /// assert_eq!(tail.to_debug_string(), "[2, 3]");
433    /// assert_eq!(
434    ///     RationalVector::from_str("()")
435    ///         .unwrap()
436    ///         .elements_ref()
437    ///         .to_debug_string(),
438    ///     "[]"
439    /// );
440    /// ```
441    #[inline]
442    fn elements_ref(&self) -> &[Rational] {
443        &self.elements
444    }
445
446    /// Returns the dimension of a [`RationalVector`]: the number of its elements.
447    ///
448    /// # Worst-case complexity
449    /// Constant time and additional memory.
450    ///
451    /// # Examples
452    /// ```
453    /// use malachite_base::vector::Vector;
454    /// use malachite_q::Rational;
455    /// use malachite_q::rational_vector::RationalVector;
456    ///
457    /// let v = RationalVector {
458    ///     elements: vec![Rational::from(4u32), Rational::from(5u32)],
459    /// };
460    /// assert_eq!(v.dimension(), 2);
461    /// assert_eq!(
462    ///     RationalVector {
463    ///         elements: Vec::new()
464    ///     }
465    ///     .dimension(),
466    ///     0
467    /// );
468    /// ```
469    #[inline]
470    fn dimension(&self) -> u64 {
471        u64::exact_from(self.elements.len())
472    }
473
474    /// Returns the pivot of a [`RationalVector`]: its first nonzero element.
475    ///
476    /// This is the element that leads the vector when it is a row of a matrix in echelon form. It
477    /// returns a reference to it, or `None` if every element is zero, which includes the
478    /// 0-dimensional vector.
479    ///
480    /// # Worst-case complexity
481    /// $T(n) = O(n)$
482    ///
483    /// $M(n) = O(1)$
484    ///
485    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`.
486    ///
487    /// # Examples
488    /// ```
489    /// use core::str::FromStr;
490    /// use malachite_base::vector::Vector;
491    /// use malachite_q::Rational;
492    /// use malachite_q::rational_vector::RationalVector;
493    ///
494    /// assert_eq!(
495    ///     RationalVector::from_str("(0, 0, -3/4, 0, 5)")
496    ///         .unwrap()
497    ///         .pivot(),
498    ///     Some(&Rational::from_signeds(-3, 4))
499    /// );
500    /// assert_eq!(RationalVector::from_str("(0, 0)").unwrap().pivot(), None);
501    /// assert_eq!(RationalVector::from_str("()").unwrap().pivot(), None);
502    /// ```
503    #[inline]
504    fn pivot(&self) -> Option<&Rational> {
505        self.elements.iter().find(|x| **x != 0u32)
506    }
507
508    /// Returns the index of the pivot of a [`RationalVector`]: the position of its first nonzero
509    /// element.
510    ///
511    /// Indices start at 0, as they do for [`Index`](core::ops::Index). Returns `None` if every
512    /// element is zero, which includes the 0-dimensional vector. When it returns `Some(i)`,
513    /// [`pivot`](Self::pivot) is the element at `i`.
514    ///
515    /// # Worst-case complexity
516    /// $T(n) = O(n)$
517    ///
518    /// $M(n) = O(1)$
519    ///
520    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`.
521    ///
522    /// # Examples
523    /// ```
524    /// use core::str::FromStr;
525    /// use malachite_base::vector::Vector;
526    /// use malachite_q::rational_vector::RationalVector;
527    ///
528    /// assert_eq!(
529    ///     RationalVector::from_str("(0, 0, -3/4, 0, 5)")
530    ///         .unwrap()
531    ///         .pivot_index(),
532    ///     Some(2)
533    /// );
534    /// assert_eq!(
535    ///     RationalVector::from_str("(0, 0)").unwrap().pivot_index(),
536    ///     None
537    /// );
538    /// assert_eq!(RationalVector::from_str("()").unwrap().pivot_index(), None);
539    /// ```
540    #[inline]
541    fn pivot_index(&self) -> Option<u64> {
542        self.elements
543            .iter()
544            .position(|x| *x != 0u32)
545            .map(u64::exact_from)
546    }
547
548    /// Returns the index of an element of largest height of a [`RationalVector`]: the first one,
549    /// when several are tied.
550    ///
551    /// Indices start at 0, as they do for [`Index`](core::ops::Index). Returns `None` for the
552    /// 0-dimensional vector.
553    ///
554    /// # Worst-case complexity
555    /// $T(n) = O(n)$
556    ///
557    /// $M(n) = O(1)$
558    ///
559    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
560    /// elements.
561    ///
562    /// # Examples
563    /// ```
564    /// use core::str::FromStr;
565    /// use malachite_base::vector::Vector;
566    /// use malachite_q::rational_vector::RationalVector;
567    ///
568    /// assert_eq!(
569    ///     RationalVector::from_str("(1/2, -3, 1/4)")
570    ///         .unwrap()
571    ///         .height_index(),
572    ///     Some(2)
573    /// );
574    /// assert_eq!(
575    ///     RationalVector::from_str("(3, -1/3)")
576    ///         .unwrap()
577    ///         .height_index(),
578    ///     Some(0)
579    /// );
580    /// assert_eq!(RationalVector::from_str("()").unwrap().height_index(), None);
581    /// ```
582    #[inline]
583    fn height_index(&self) -> Option<u64> {
584        // `max_by` returns the last of several equal maxima, so iterating in reverse gives the
585        // first.
586        self.elements
587            .iter()
588            .enumerate()
589            .rev()
590            .max_by(|(_, x), (_, y)| x.height_ref().cmp(y.height_ref()))
591            .map(|(i, _)| u64::exact_from(i))
592    }
593
594    /// Determines whether every element of a [`RationalVector`] is zero.
595    ///
596    /// The 0-dimensional vector, which has no elements, counts as zero.
597    ///
598    /// # Worst-case complexity
599    /// $T(n) = O(n)$
600    ///
601    /// $M(n) = O(1)$
602    ///
603    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`.
604    ///
605    /// # Examples
606    /// ```
607    /// use core::str::FromStr;
608    /// use malachite_base::vector::Vector;
609    /// use malachite_q::rational_vector::RationalVector;
610    ///
611    /// assert!(RationalVector::from_str("(0, 0)").unwrap().is_zero());
612    /// assert!(RationalVector::from_str("()").unwrap().is_zero());
613    /// assert!(!RationalVector::from_str("(0, 1, 0)").unwrap().is_zero());
614    /// ```
615    #[inline]
616    fn is_zero(&self) -> bool {
617        self.elements.iter().all(|x| *x == 0u32)
618    }
619
620    /// Determines whether a [`RationalVector`] is a standard basis vector, returning the index of
621    /// its 1 if it is.
622    ///
623    /// A standard basis vector has a single element equal to 1 and every other element 0. Returns
624    /// `None` for every other vector, including the zero vectors and the 0-dimensional vector.
625    ///
626    /// # Worst-case complexity
627    /// $T(n) = O(n)$
628    ///
629    /// $M(n) = O(1)$
630    ///
631    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`.
632    ///
633    /// # Examples
634    /// ```
635    /// use core::str::FromStr;
636    /// use malachite_base::vector::Vector;
637    /// use malachite_q::rational_vector::RationalVector;
638    ///
639    /// assert_eq!(
640    ///     RationalVector::from_str("(0, 1, 0)")
641    ///         .unwrap()
642    ///         .standard_basis_index(),
643    ///     Some(1)
644    /// );
645    /// assert_eq!(
646    ///     RationalVector::from_str("(0, 1/2, 0)")
647    ///         .unwrap()
648    ///         .standard_basis_index(),
649    ///     None
650    /// );
651    /// assert_eq!(
652    ///     RationalVector::from_str("(1, 0, 1)")
653    ///         .unwrap()
654    ///         .standard_basis_index(),
655    ///     None
656    /// );
657    /// assert_eq!(
658    ///     RationalVector::from_str("(0, 0)")
659    ///         .unwrap()
660    ///         .standard_basis_index(),
661    ///     None
662    /// );
663    /// ```
664    fn standard_basis_index(&self) -> Option<u64> {
665        let index = self.pivot_index()?;
666        let i = usize::exact_from(index);
667        if self.elements[i] == 1u32 && self.elements[i + 1..].iter().all(|x| *x == 0u32) {
668            Some(index)
669        } else {
670            None
671        }
672    }
673
674    /// Returns the number of significant bits of the height of a [`RationalVector`], together with
675    /// whether any of its elements is negative.
676    ///
677    /// The bit count is that of the largest of the elements' heights, $\max(|p|, q)$ for $p/q$ in
678    /// lowest terms.
679    ///
680    /// # Worst-case complexity
681    /// $T(n) = O(n)$
682    ///
683    /// $M(n) = O(1)$
684    ///
685    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
686    /// elements' numerators and denominators.
687    ///
688    /// # Examples
689    /// ```
690    /// use core::str::FromStr;
691    /// use malachite_base::vector::Vector;
692    /// use malachite_q::rational_vector::RationalVector;
693    ///
694    /// assert_eq!(
695    ///     RationalVector::from_str("(1/4, -2)").unwrap().max_bits(),
696    ///     (3, true)
697    /// );
698    /// assert_eq!(
699    ///     RationalVector::from_str("()").unwrap().max_bits(),
700    ///     (0, false)
701    /// );
702    /// ```
703    #[inline]
704    fn max_bits(&self) -> (u64, bool) {
705        (
706            self.height_significant_bits(),
707            self.elements.iter().any(|x| *x < 0u32),
708        )
709    }
710
711    /// Returns the number of significant bits of the sum of the absolute values of the elements of
712    /// a [`RationalVector`] (its $\ell^1$ norm), together with the number of significant bits of
713    /// its height.
714    ///
715    /// The $\ell^1$ norm is a rational number, and, as for a single [`Rational`], its number of
716    /// significant bits is the sum of those of its numerator and denominator. So a norm of 0, which
717    /// is $0/1$, has 1 significant bit, even for the 0-dimensional vector.
718    ///
719    /// # Worst-case complexity
720    /// $T(n) = O(n)$
721    ///
722    /// $M(n) = O(n)$
723    ///
724    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
725    /// elements' numerators and denominators.
726    ///
727    /// # Examples
728    /// ```
729    /// use core::str::FromStr;
730    /// use malachite_base::vector::Vector;
731    /// use malachite_q::rational_vector::RationalVector;
732    ///
733    /// assert_eq!(
734    ///     RationalVector::from_str("(1/2, -1/3)")
735    ///         .unwrap()
736    ///         .sum_max_bits(),
737    ///     (6, 2)
738    /// );
739    /// assert_eq!(
740    ///     RationalVector::from_str("()").unwrap().sum_max_bits(),
741    ///     (1, 0)
742    /// );
743    /// ```
744    fn sum_max_bits(&self) -> (u64, u64) {
745        (
746            self.l1_norm_significant_bits(),
747            self.height_significant_bits(),
748        )
749    }
750}
751
752// Implements `Named` for `RationalVector`.
753impl_named!(RationalVector);
754
755/// `ShortlexRationalVector` is a wrapper around a [`RationalVector`], taking the [`RationalVector`]
756/// by value.
757///
758/// [`RationalVector`] does not implement [`Ord`], because no order on vectors is canonical: lex,
759/// graded lex, and the others all have their uses, and the order most natural mathematically,
760/// comparing vectors of the same dimension element by element, is only partial. Wrapping a
761/// [`RationalVector`] in a `ShortlexRationalVector` provides one total order: vectors are compared
762/// first by dimension and then, in case of a tie, lexicographically, by their elements from first
763/// to last. Its equality agrees with [`RationalVector`] equality.
764///
765/// Unlike lexicographic order on [`Vec`]s, this order puts every vector of a smaller dimension
766/// before every vector of a larger one, so that $(5) < (0, 0)$. It is not a well-order, since the
767/// [`Rational`]s are not: $(0) > (-1) > (-2) > \ldots$ descends forever.
768///
769/// `ShortlexRationalVector` owns its value. This is useful in many cases, for example if you want
770/// to use [`RationalVector`]s as keys in a [`BTreeMap`](alloc::collections::BTreeMap). In other
771/// situations, it is better to use [`ShortlexRationalVectorRef`], which only has a reference to its
772/// value.
773// Serialized as its inner `RationalVector`, since the wrapper adds no data of its own.
774#[derive(Clone, Debug, Eq, Hash, PartialEq)]
775#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
776#[cfg_attr(feature = "serde", serde(transparent))]
777pub struct ShortlexRationalVector(pub RationalVector);
778
779/// `ShortlexRationalVectorRef` is a wrapper around a [`RationalVector`], taking the
780/// [`RationalVector`] by reference.
781///
782/// See the [`ShortlexRationalVector`] documentation for details.
783#[derive(Clone, Debug, Eq, Hash, PartialEq)]
784pub struct ShortlexRationalVectorRef<'a>(pub &'a RationalVector);
785
786impl ShortlexRationalVector {
787    /// Borrows a [`ShortlexRationalVector`] as a [`ShortlexRationalVectorRef`].
788    ///
789    /// # Worst-case complexity
790    /// Constant time and additional memory.
791    ///
792    /// # Examples
793    /// ```
794    /// use core::str::FromStr;
795    /// use malachite_q::rational_vector::{
796    ///     RationalVector, ShortlexRationalVector, ShortlexRationalVectorRef,
797    /// };
798    ///
799    /// let v = RationalVector::from_str("(1, 2, 3)").unwrap();
800    /// let x = ShortlexRationalVector(v.clone());
801    /// assert_eq!(x.as_ref(), ShortlexRationalVectorRef(&v));
802    /// ```
803    pub const fn as_ref(&self) -> ShortlexRationalVectorRef<'_> {
804        ShortlexRationalVectorRef(&self.0)
805    }
806}
807
808impl Deref for ShortlexRationalVector {
809    type Target = RationalVector;
810
811    /// Allows a [`ShortlexRationalVector`] to dereference to a [`RationalVector`].
812    ///
813    /// ```
814    /// use core::str::FromStr;
815    /// use malachite_q::rational_vector::{RationalVector, ShortlexRationalVector};
816    ///
817    /// let v = RationalVector::from_str("(1, 2, 3)").unwrap();
818    /// let x = ShortlexRationalVector(v.clone());
819    /// assert_eq!(*x, v);
820    /// ```
821    fn deref(&self) -> &RationalVector {
822        &self.0
823    }
824}
825
826impl Deref for ShortlexRationalVectorRef<'_> {
827    type Target = RationalVector;
828
829    /// Allows a [`ShortlexRationalVectorRef`] to dereference to a [`RationalVector`].
830    ///
831    /// ```
832    /// use core::str::FromStr;
833    /// use malachite_q::rational_vector::{RationalVector, ShortlexRationalVectorRef};
834    ///
835    /// let v = RationalVector::from_str("(1, 2, 3)").unwrap();
836    /// let x = ShortlexRationalVectorRef(&v);
837    /// assert_eq!(*x, v);
838    /// ```
839    fn deref(&self) -> &RationalVector {
840        self.0
841    }
842}