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}