ndarray/dimension/
dynindeximpl.rs

1use crate::imp_prelude::*;
2#[cfg(not(feature = "std"))]
3use alloc::boxed::Box;
4use alloc::vec;
5#[cfg(not(feature = "std"))]
6use alloc::vec::Vec;
7use std::hash::{Hash, Hasher};
8use std::ops::{Deref, DerefMut, Index, IndexMut};
9const CAP: usize = 4;
10
11/// T is usize or isize
12#[derive(Debug)]
13enum IxDynRepr<T>
14{
15    Inline(u32, [T; CAP]),
16    Alloc(Box<[T]>),
17}
18
19impl<T> Deref for IxDynRepr<T>
20{
21    type Target = [T];
22    fn deref(&self) -> &[T]
23    {
24        match *self {
25            IxDynRepr::Inline(len, ref ar) => {
26                debug_assert!(len as usize <= ar.len());
27                unsafe { ar.get_unchecked(..len as usize) }
28            }
29            IxDynRepr::Alloc(ref ar) => ar,
30        }
31    }
32}
33
34impl<T> DerefMut for IxDynRepr<T>
35{
36    fn deref_mut(&mut self) -> &mut [T]
37    {
38        match *self {
39            IxDynRepr::Inline(len, ref mut ar) => {
40                debug_assert!(len as usize <= ar.len());
41                unsafe { ar.get_unchecked_mut(..len as usize) }
42            }
43            IxDynRepr::Alloc(ref mut ar) => ar,
44        }
45    }
46}
47
48/// The default is equivalent to `Self::from(&[0])`.
49impl Default for IxDynRepr<Ix>
50{
51    fn default() -> Self
52    {
53        Self::copy_from(&[0])
54    }
55}
56
57use num_traits::Zero;
58
59impl<T: Copy + Zero> IxDynRepr<T>
60{
61    pub fn copy_from(x: &[T]) -> Self
62    {
63        if x.len() <= CAP {
64            let mut arr = [T::zero(); CAP];
65            arr[..x.len()].copy_from_slice(x);
66            IxDynRepr::Inline(x.len() as _, arr)
67        } else {
68            Self::from(x)
69        }
70    }
71}
72
73impl<T: Copy + Zero> IxDynRepr<T>
74{
75    // make an Inline or Alloc version as appropriate
76    fn from_vec_auto(v: Vec<T>) -> Self
77    {
78        if v.len() <= CAP {
79            Self::copy_from(&v)
80        } else {
81            Self::from_vec(v)
82        }
83    }
84}
85
86impl<T: Copy> IxDynRepr<T>
87{
88    fn from_vec(v: Vec<T>) -> Self
89    {
90        IxDynRepr::Alloc(v.into_boxed_slice())
91    }
92
93    fn from(x: &[T]) -> Self
94    {
95        Self::from_vec(x.to_vec())
96    }
97}
98
99impl<T: Copy> Clone for IxDynRepr<T>
100{
101    fn clone(&self) -> Self
102    {
103        match *self {
104            IxDynRepr::Inline(len, arr) => IxDynRepr::Inline(len, arr),
105            _ => Self::from(&self[..]),
106        }
107    }
108}
109
110impl<T: Eq> Eq for IxDynRepr<T> {}
111
112impl<T: PartialEq> PartialEq for IxDynRepr<T>
113{
114    fn eq(&self, rhs: &Self) -> bool
115    {
116        match (self, rhs) {
117            (&IxDynRepr::Inline(slen, ref sarr), &IxDynRepr::Inline(rlen, ref rarr)) =>
118                slen == rlen
119                    && (0..CAP)
120                        .filter(|&i| i < slen as usize)
121                        .all(|i| sarr[i] == rarr[i]),
122            _ => self[..] == rhs[..],
123        }
124    }
125}
126
127impl<T: Hash> Hash for IxDynRepr<T>
128{
129    fn hash<H: Hasher>(&self, state: &mut H)
130    {
131        Hash::hash(&self[..], state)
132    }
133}
134
135/// Dynamic dimension or index type.
136///
137/// Use `IxDyn` directly. This type implements a dynamic number of
138/// dimensions or indices. Short dimensions are stored inline and don't need
139/// any dynamic memory allocation.
140#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
141pub struct IxDynImpl(IxDynRepr<Ix>);
142
143impl IxDynImpl
144{
145    pub(crate) fn insert(&self, i: usize) -> Self
146    {
147        let len = self.len();
148        debug_assert!(i <= len);
149        IxDynImpl(if len < CAP {
150            let mut out = [1; CAP];
151            out[0..i].copy_from_slice(&self[0..i]);
152            out[i + 1..=len].copy_from_slice(&self[i..len]);
153            IxDynRepr::Inline((len + 1) as u32, out)
154        } else {
155            let mut out = Vec::with_capacity(len + 1);
156            out.extend_from_slice(&self[0..i]);
157            out.push(1);
158            out.extend_from_slice(&self[i..len]);
159            IxDynRepr::from_vec(out)
160        })
161    }
162
163    fn remove(&self, i: usize) -> Self
164    {
165        IxDynImpl(match self.0 {
166            IxDynRepr::Inline(0, _) => IxDynRepr::Inline(0, [0; CAP]),
167            IxDynRepr::Inline(1, _) => IxDynRepr::Inline(0, [0; CAP]),
168            IxDynRepr::Inline(2, ref arr) => {
169                let mut out = [0; CAP];
170                out[0] = arr[1 - i];
171                IxDynRepr::Inline(1, out)
172            }
173            ref ixdyn => {
174                let len = ixdyn.len();
175                let mut result = IxDynRepr::copy_from(&ixdyn[..len - 1]);
176                for j in i..len - 1 {
177                    result[j] = ixdyn[j + 1]
178                }
179                result
180            }
181        })
182    }
183}
184
185impl<'a> From<&'a [Ix]> for IxDynImpl
186{
187    #[inline]
188    fn from(ix: &'a [Ix]) -> Self
189    {
190        IxDynImpl(IxDynRepr::copy_from(ix))
191    }
192}
193
194impl From<Vec<Ix>> for IxDynImpl
195{
196    #[inline]
197    fn from(ix: Vec<Ix>) -> Self
198    {
199        IxDynImpl(IxDynRepr::from_vec_auto(ix))
200    }
201}
202
203impl<J> Index<J> for IxDynImpl
204where [Ix]: Index<J>
205{
206    type Output = <[Ix] as Index<J>>::Output;
207    fn index(&self, index: J) -> &Self::Output
208    {
209        &self.0[index]
210    }
211}
212
213impl<J> IndexMut<J> for IxDynImpl
214where [Ix]: IndexMut<J>
215{
216    fn index_mut(&mut self, index: J) -> &mut Self::Output
217    {
218        &mut self.0[index]
219    }
220}
221
222impl Deref for IxDynImpl
223{
224    type Target = [Ix];
225    #[inline]
226    fn deref(&self) -> &[Ix]
227    {
228        &self.0
229    }
230}
231
232impl DerefMut for IxDynImpl
233{
234    #[inline]
235    fn deref_mut(&mut self) -> &mut [Ix]
236    {
237        &mut self.0
238    }
239}
240
241impl<'a> IntoIterator for &'a IxDynImpl
242{
243    type Item = &'a Ix;
244    type IntoIter = <&'a [Ix] as IntoIterator>::IntoIter;
245    #[inline]
246    fn into_iter(self) -> Self::IntoIter
247    {
248        self[..].iter()
249    }
250}
251
252impl RemoveAxis for Dim<IxDynImpl>
253{
254    fn remove_axis(&self, axis: Axis) -> Self
255    {
256        debug_assert!(axis.index() < self.ndim());
257        Dim::new(self.ix().remove(axis.index()))
258    }
259}
260
261impl IxDyn
262{
263    /// Create a new dimension value with `n` axes, all zeros
264    #[inline]
265    pub fn zeros(n: usize) -> IxDyn
266    {
267        const ZEROS: &[usize] = &[0; 4];
268        if n <= ZEROS.len() {
269            Dim(&ZEROS[..n])
270        } else {
271            Dim(vec![0; n])
272        }
273    }
274}