malachite_base/rational_sequences/
access.rs

1// Copyright © 2025 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_sequences::{RationalSequence, rational_sequence_reduce};
10use core::ops::Index;
11
12impl<T: Eq> Index<usize> for RationalSequence<T> {
13    type Output = T;
14
15    /// Gets a reference to an element of a [`RationalSequence`] at an index.
16    ///
17    /// If the index is greater than or equal to the length of the sequence, this function panics.
18    ///
19    /// # Worst-case complexity
20    /// Constant time and additional memory.
21    ///
22    /// # Panics
23    /// Panics if `index` is greater than or equal to the length of this sequence.
24    ///
25    /// # Examples
26    /// ```
27    /// use malachite_base::rational_sequences::RationalSequence;
28    ///
29    /// assert_eq!(RationalSequence::from_slices(&[1, 2], &[3, 4])[1], 2);
30    /// assert_eq!(RationalSequence::from_slices(&[1, 2], &[3, 4])[10], 3);
31    /// ```
32    #[inline]
33    fn index(&self, i: usize) -> &T {
34        self.get(i).unwrap()
35    }
36}
37
38impl<T: Eq> RationalSequence<T> {
39    /// Gets a reference to an element of a [`RationalSequence`] at an index.
40    ///
41    /// If the index is greater than or equal to the length of the sequence, `None` is returned.
42    ///
43    /// # Worst-case complexity
44    /// Constant time and additional memory.
45    ///
46    /// # Examples
47    /// ```
48    /// use malachite_base::rational_sequences::RationalSequence;
49    ///
50    /// assert_eq!(
51    ///     RationalSequence::from_slices(&[1, 2], &[3, 4]).get(1),
52    ///     Some(&2)
53    /// );
54    /// assert_eq!(
55    ///     RationalSequence::from_slices(&[1, 2], &[3, 4]).get(10),
56    ///     Some(&3)
57    /// );
58    /// ```
59    pub fn get(&self, i: usize) -> Option<&T> {
60        let non_repeating_len = self.non_repeating.len();
61        if i < non_repeating_len {
62            Some(&self.non_repeating[i])
63        } else if self.repeating.is_empty() {
64            None
65        } else {
66            Some(&self.repeating[(i - non_repeating_len) % self.repeating.len()])
67        }
68    }
69}
70
71impl<T: Clone + Eq> RationalSequence<T> {
72    /// Mutates an element of a [`RationalSequence`] at an index using a provided closure, and then
73    /// returns whatever the closure returns.
74    ///
75    /// If the index is greater than or equal to the length of the sequence, this function panics.
76    ///
77    /// # Worst-case complexity
78    /// $T(n) = O(n)$
79    ///
80    /// $M(n) = O(n)$
81    ///
82    /// where $T$ is time, $M$ is additional memory, and $n$ is `index`.
83    ///
84    /// # Panics
85    /// Panics if `index` is greater than or equal to the length of this sequence.
86    ///
87    /// # Examples
88    /// ```
89    /// use malachite_base::rational_sequences::RationalSequence;
90    ///
91    /// let mut xs = RationalSequence::from_slices(&[1, 2], &[3, 4]);
92    /// assert_eq!(
93    ///     xs.mutate(1, |x| {
94    ///         *x = 100;
95    ///         25
96    ///     }),
97    ///     25
98    /// );
99    /// assert_eq!(xs, RationalSequence::from_slices(&[1, 100], &[3, 4]));
100    ///
101    /// let mut xs = RationalSequence::from_slices(&[1, 2], &[3, 4]);
102    /// assert_eq!(
103    ///     xs.mutate(6, |x| {
104    ///         *x = 100;
105    ///         25
106    ///     }),
107    ///     25
108    /// );
109    /// assert_eq!(
110    ///     xs,
111    ///     RationalSequence::from_slices(&[1, 2, 3, 4, 3, 4, 100], &[4, 3])
112    /// );
113    /// ```
114    pub fn mutate<F: FnOnce(&mut T) -> U, U>(&mut self, i: usize, f: F) -> U {
115        let non_repeating_len = self.non_repeating.len();
116        let result = if i < non_repeating_len {
117            f(&mut self.non_repeating[i])
118        } else if self.repeating.is_empty() {
119            panic!("index out of bounds");
120        } else {
121            let repeating_len = self.repeating.len();
122            let extra = i - non_repeating_len + 1;
123            self.non_repeating
124                .extend(self.repeating.iter().cycle().take(extra).cloned());
125            self.repeating.rotate_left(extra % repeating_len);
126            f(&mut self.non_repeating[i])
127        };
128        rational_sequence_reduce(&mut self.non_repeating, &mut self.repeating);
129        result
130    }
131}