1use crate::prelude_dev::*;
7
8pub fn index_select_f<R, T, B, D, I>(tensor: &TensorAny<R, T, B, D>, axis: isize, indices: I) -> Result<Tensor<T, B, D>>
11where
12 R: DataAPI<Data = <B as DeviceRawAPI<T>>::Raw>,
13 D: DimAPI + DimSmallerOneAPI,
14 D::SmallerOne: DimAPI,
15 B: DeviceAPI<T> + DeviceIndexSelectAPI<T, D> + DeviceCreationAnyAPI<T>,
16 I: TryInto<AxesIndex<isize>, Error: Into<Error>>,
17{
18 let device = tensor.device().clone();
20 let tensor_layout = tensor.layout();
21 let ndim = tensor_layout.ndim();
22 let axis = rstsr_check_axis!(axis, ndim)?;
24 let nshape: usize = tensor_layout.shape()[axis];
25 let indices = indices.try_into().map_err(Into::into)?;
26 let indices = indices
27 .as_ref()
28 .iter()
29 .map(|&i| -> Result<usize> {
30 let i = if i < 0 { nshape as isize + i } else { i };
31 rstsr_pattern!(
32 i,
33 0..nshape as isize,
34 IndexError,
35 "Invalid index that exceeds shape length at axis {}.",
36 axis
37 )?;
38 Ok(i as usize)
39 })
40 .collect::<Result<Vec<usize>>>()?;
41 let mut out_shape = tensor_layout.shape().as_ref().to_vec();
42 out_shape[axis] = indices.len();
43 let out_layout = out_shape.new_contig(None, device.default_order()).into_dim()?;
44 let mut out_storage = device.uninit_impl(out_layout.size())?;
45 device.index_select(out_storage.raw_mut(), &out_layout, tensor.storage().raw(), tensor_layout, axis, &indices)?;
46 let out_storage = unsafe { B::assume_init_impl(out_storage)? };
47 TensorBase::new_f(out_storage, out_layout)
48}
49
50pub fn index_select<R, T, B, D, I>(tensor: &TensorAny<R, T, B, D>, axis: isize, indices: I) -> Tensor<T, B, D>
57where
58 R: DataAPI<Data = <B as DeviceRawAPI<T>>::Raw>,
59 D: DimAPI + DimSmallerOneAPI,
60 D::SmallerOne: DimAPI,
61 B: DeviceAPI<T> + DeviceIndexSelectAPI<T, D> + DeviceCreationAnyAPI<T>,
62 I: TryInto<AxesIndex<isize>, Error: Into<Error>>,
63{
64 index_select_f(tensor, axis, indices).rstsr_unwrap()
65}
66
67pub fn take_f<R, T, B, D, I>(tensor: &TensorAny<R, T, B, D>, indices: I, axis: isize) -> Result<Tensor<T, B, D>>
68where
69 R: DataAPI<Data = <B as DeviceRawAPI<T>>::Raw>,
70 D: DimAPI + DimSmallerOneAPI,
71 D::SmallerOne: DimAPI,
72 B: DeviceAPI<T> + DeviceIndexSelectAPI<T, D> + DeviceCreationAnyAPI<T>,
73 I: TryInto<AxesIndex<isize>, Error: Into<Error>>,
74{
75 index_select_f(tensor, axis, indices)
76}
77
78pub fn take<R, T, B, D, I>(tensor: &TensorAny<R, T, B, D>, indices: I, axis: isize) -> Tensor<T, B, D>
84where
85 R: DataAPI<Data = <B as DeviceRawAPI<T>>::Raw>,
86 D: DimAPI + DimSmallerOneAPI,
87 D::SmallerOne: DimAPI,
88 B: DeviceAPI<T> + DeviceIndexSelectAPI<T, D> + DeviceCreationAnyAPI<T>,
89 I: TryInto<AxesIndex<isize>, Error: Into<Error>>,
90{
91 index_select(tensor, axis, indices)
92}
93
94impl<R, T, B, D> TensorAny<R, T, B, D>
95where
96 R: DataAPI<Data = <B as DeviceRawAPI<T>>::Raw>,
97 D: DimAPI + DimSmallerOneAPI,
98 D::SmallerOne: DimAPI,
99 B: DeviceAPI<T> + DeviceIndexSelectAPI<T, D> + DeviceCreationAnyAPI<T>,
100{
101 pub fn index_select_f<I>(&self, axis: isize, indices: I) -> Result<Tensor<T, B, D>>
102 where
103 I: TryInto<AxesIndex<isize>, Error: Into<Error>>,
104 {
105 index_select_f(self, axis, indices)
106 }
107
108 pub fn index_select<I>(&self, axis: isize, indices: I) -> Tensor<T, B, D>
115 where
116 I: TryInto<AxesIndex<isize>, Error: Into<Error>>,
117 {
118 index_select(self, axis, indices)
119 }
120
121 pub fn take_f<I>(&self, indices: I, axis: isize) -> Result<Tensor<T, B, D>>
122 where
123 I: TryInto<AxesIndex<isize>, Error: Into<Error>>,
124 {
125 take_f(self, indices, axis)
126 }
127
128 pub fn take<I>(&self, indices: I, axis: isize) -> Tensor<T, B, D>
134 where
135 I: TryInto<AxesIndex<isize>, Error: Into<Error>>,
136 {
137 take(self, indices, axis)
138 }
139}
140
141pub fn bool_select_f<R, T, B, D, I>(tensor: &TensorAny<R, T, B, D>, axis: isize, mask: I) -> Result<Tensor<T, B, D>>
146where
147 R: DataAPI<Data = <B as DeviceRawAPI<T>>::Raw>,
148 D: DimAPI + DimSmallerOneAPI,
149 D::SmallerOne: DimAPI,
150 B: DeviceAPI<T> + DeviceIndexSelectAPI<T, D> + DeviceCreationAnyAPI<T>,
151 I: TryInto<AxesIndex<bool>, Error: Into<Error>>,
152{
153 let indices = mask
155 .try_into()
156 .map_err(Into::into)?
157 .as_ref()
158 .iter()
159 .enumerate()
160 .filter_map(|(i, &m)| m.then_some(i))
161 .collect::<Vec<usize>>();
162 index_select_f(tensor, axis, indices)
163}
164
165pub fn bool_select<R, T, B, D, I>(tensor: &TensorAny<R, T, B, D>, axis: isize, mask: I) -> Tensor<T, B, D>
168where
169 R: DataAPI<Data = <B as DeviceRawAPI<T>>::Raw>,
170 D: DimAPI + DimSmallerOneAPI,
171 D::SmallerOne: DimAPI,
172 B: DeviceAPI<T> + DeviceIndexSelectAPI<T, D> + DeviceCreationAnyAPI<T>,
173 I: TryInto<AxesIndex<bool>, Error: Into<Error>>,
174{
175 bool_select_f(tensor, axis, mask).rstsr_unwrap()
176}
177
178impl<R, T, B, D> TensorAny<R, T, B, D>
179where
180 R: DataAPI<Data = <B as DeviceRawAPI<T>>::Raw>,
181 D: DimAPI + DimSmallerOneAPI,
182 D::SmallerOne: DimAPI,
183 B: DeviceAPI<T> + DeviceIndexSelectAPI<T, D> + DeviceCreationAnyAPI<T>,
184{
185 pub fn bool_select_f<I>(&self, axis: isize, indices: I) -> Result<Tensor<T, B, D>>
186 where
187 I: TryInto<AxesIndex<bool>, Error: Into<Error>>,
188 {
189 bool_select_f(self, axis, indices)
190 }
191
192 pub fn bool_select<I>(&self, axis: isize, indices: I) -> Tensor<T, B, D>
195 where
196 I: TryInto<AxesIndex<bool>, Error: Into<Error>>,
197 {
198 bool_select(self, axis, indices)
199 }
200}
201
202#[cfg(test)]
205mod test {
206 use super::*;
207
208 #[test]
209 fn test_index_select() {
210 #[cfg(not(feature = "col_major"))]
211 {
212 let device = DeviceCpuSerial::default();
213 let a = linspace((1.0, 24.0, 24, &device)).into_shape((2, 3, 4));
214 let b = a.index_select(0, [0, 0, 1, -1]);
215 assert!(fingerprint(&b) - -31.94175930917264 < 1e-8);
216 let b = a.index_select(1, [0, 0, 1, -1]);
217 assert!(fingerprint(&b) - 3.5719025258942088 < 1e-8);
218 let b = a.index_select(2, [0, 0, 1, -1]);
219 assert!(fingerprint(&b) - -25.648600916145096 < 1e-8);
220 }
221 #[cfg(feature = "col_major")]
222 {
223 let device = DeviceCpuSerial::default();
224 let a = linspace((1.0, 24.0, 24, &device)).into_shape((4, 3, 2));
225 let b = a.index_select(2, [0, 0, 1, -1]);
226 assert!(fingerprint(&b) - -31.94175930917264 < 1e-8);
227 let b = a.index_select(1, [0, 0, 1, -1]);
228 assert!(fingerprint(&b) - 3.5719025258942088 < 1e-8);
229 let b = a.index_select(0, [0, 0, 1, -1]);
230 assert!(fingerprint(&b) - -25.648600916145096 < 1e-8);
231 }
232
233 let device = DeviceCpuSerial::default();
235 let a = linspace((1.0, 4.0, 4, &device));
236 let mask: Vec<usize> = vec![];
237 let b = a.index_select(0, &mask);
238 assert_eq!(b.raw(), &[]);
239 }
240
241 #[test]
242 fn test_index_select_default_device() {
243 #[cfg(not(feature = "col_major"))]
244 {
245 let device = DeviceCpu::default();
246 let a = linspace((1.0, 2.0, 256 * 256 * 256, &device)).into_shape((256, 256, 256));
247 let sel = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233];
248 let b = a.index_select(0, sel);
249 assert!(fingerprint(&b) - 0.9357016252766746 < 1e-10);
250 let b = a.index_select(1, sel);
251 assert!(fingerprint(&b) - 1.012193909979973 < 1e-10);
252 let b = a.index_select(2, sel);
253 assert!(fingerprint(&b) - 1.010735112247236 < 1e-10);
254 }
255 #[cfg(feature = "col_major")]
256 {
257 let device = DeviceCpu::default();
258 let a = linspace((1.0, 2.0, 256 * 256 * 256, &device)).into_shape((256, 256, 256));
259 let sel = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233];
260 let b = a.index_select(2, sel);
261 assert!(fingerprint(&b) - 0.9357016252766746 < 1e-10);
262 let b = a.index_select(1, sel);
263 assert!(fingerprint(&b) - 1.012193909979973 < 1e-10);
264 let b = a.index_select(0, sel);
265 assert!(fingerprint(&b) - 1.010735112247236 < 1e-10);
266 }
267 }
268
269 #[test]
270 fn test_bool_select_workable() {
271 let a = arange(24).into_shape((2, 3, 4));
272 let b = a.bool_select(-2, [true, false, true]);
273 println!("{b:?}");
274 }
275}