binius_utils/
random_access_sequence.rs1pub trait RandomAccessSequence<T: Copy> {
7 fn len(&self) -> usize;
8
9 #[inline(always)]
10 fn is_empty(&self) -> bool {
11 self.len() == 0
12 }
13
14 #[inline(always)]
15 fn get(&self, index: usize) -> T {
16 assert!(index < self.len(), "Index out of bounds");
17 unsafe { self.get_unchecked(index) }
18 }
19
20 unsafe fn get_unchecked(&self, index: usize) -> T;
25}
26
27pub trait RandomAccessSequenceMut<T: Copy>: RandomAccessSequence<T> {
29 #[inline(always)]
30 fn set(&mut self, index: usize, value: T) {
31 assert!(index < self.len(), "Index out of bounds");
32 unsafe { self.set_unchecked(index, value) }
33 }
34
35 unsafe fn set_unchecked(&mut self, index: usize, value: T);
40}
41
42impl<T: Copy> RandomAccessSequence<T> for &[T] {
43 #[inline(always)]
44 fn len(&self) -> usize {
45 <[T]>::len(self)
46 }
47
48 #[inline(always)]
49 fn get(&self, index: usize) -> T {
50 self[index]
51 }
52
53 #[inline(always)]
54 unsafe fn get_unchecked(&self, index: usize) -> T {
55 unsafe { *<[T]>::get_unchecked(self, index) }
56 }
57}
58
59impl<T: Copy> RandomAccessSequence<T> for &mut [T] {
60 #[inline(always)]
61 fn len(&self) -> usize {
62 <[T]>::len(self)
63 }
64
65 #[inline(always)]
66 fn get(&self, index: usize) -> T {
67 self[index]
68 }
69
70 #[inline(always)]
71 unsafe fn get_unchecked(&self, index: usize) -> T {
72 unsafe { *<[T]>::get_unchecked(self, index) }
73 }
74}
75
76impl<T: Copy> RandomAccessSequenceMut<T> for &mut [T] {
77 #[inline(always)]
78 fn set(&mut self, index: usize, value: T) {
79 self[index] = value;
80 }
81
82 #[inline(always)]
83 unsafe fn set_unchecked(&mut self, index: usize, value: T) {
84 unsafe {
85 *<[T]>::get_unchecked_mut(self, index) = value;
86 }
87 }
88}
89
90#[derive(Clone)]
93pub struct MatrixVertSliceSubrange<'a, T: Copy, Inner: RandomAccessSequence<T>> {
94 inner: &'a Inner,
95 log_cols: usize,
96 log_slice: usize,
97 slice_index: usize,
98 len: usize,
99 _marker: std::marker::PhantomData<T>,
100}
101
102impl<'a, T: Copy, Inner: RandomAccessSequence<T>> MatrixVertSliceSubrange<'a, T, Inner> {
103 #[inline(always)]
108 pub fn new(
109 inner: &'a Inner,
110 log_rows: usize,
111 log_cols: usize,
112 log_slice: usize,
113 slice_index: usize,
114 ) -> Self {
115 assert_eq!(
116 1 << (log_rows + log_cols),
117 inner.len(),
118 "matrix dimensions do not match inner sequence"
119 );
120 assert!(log_slice <= log_cols && slice_index < 1 << (log_cols - log_slice));
121
122 let len = 1 << (log_slice + log_rows);
123
124 Self {
125 inner,
126 log_cols,
127 log_slice,
128 slice_index,
129 len,
130 _marker: std::marker::PhantomData,
131 }
132 }
133}
134
135impl<T: Copy, Inner: RandomAccessSequence<T>> RandomAccessSequence<T>
136 for MatrixVertSliceSubrange<'_, T, Inner>
137{
138 #[inline(always)]
139 fn len(&self) -> usize {
140 self.len
141 }
142
143 #[inline(always)]
144 unsafe fn get_unchecked(&self, index: usize) -> T {
145 let row = index >> self.log_slice;
146 let col = index ^ (row << self.log_slice);
147 let inner_index = row << self.log_cols | self.slice_index << self.log_slice | col;
148 unsafe { self.inner.get_unchecked(inner_index) }
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use std::fmt::Debug;
155
156 use rand::prelude::*;
157
158 use super::*;
159
160 fn check_collection<T: Copy + Eq + Debug>(
161 collection: &impl RandomAccessSequence<T>,
162 expected: &[T],
163 ) {
164 assert_eq!(collection.len(), expected.len());
165
166 for (i, v) in expected.iter().enumerate() {
167 assert_eq!(&collection.get(i), v);
168 assert_eq!(&unsafe { collection.get_unchecked(i) }, v);
169 }
170 }
171
172 fn check_collection_get_set<T: Eq + Copy + Debug>(
173 collection: &mut impl RandomAccessSequenceMut<T>,
174 random: &mut impl FnMut() -> T,
175 ) {
176 for i in 0..collection.len() {
177 let value = random();
178 collection.set(i, value);
179 assert_eq!(collection.get(i), value);
180 assert_eq!(unsafe { collection.get_unchecked(i) }, value);
181 }
182 }
183
184 #[test]
185 fn check_slice() {
186 let slice: &[usize] = &[];
187 check_collection::<usize>(&slice, slice);
188
189 let slice: &[usize] = &[1usize, 2, 3];
190 check_collection(&slice, slice);
191 }
192
193 #[test]
194 fn check_slice_mut() {
195 let mut rng = StdRng::seed_from_u64(0);
196 let mut random = || -> usize { rng.random::<u64>() as usize };
197
198 let mut slice: &mut [usize] = &mut [];
199
200 check_collection(&slice, slice);
201 check_collection_get_set(&mut slice, &mut random);
202
203 let mut slice: &mut [usize] = &mut [1, 2, 3];
204 check_collection(&slice, slice);
205 check_collection_get_set(&mut slice, &mut random);
206 }
207}