Skip to main content

rstsr_core/tensor/manuplication/
into_dim.rs

1use crate::prelude_dev::*;
2
3/// Convert layout to the other dimension.
4///
5/// See also [`to_dim`].
6pub fn into_dim_f<S, D, D2>(tensor: TensorBase<S, D>) -> Result<TensorBase<S, D2>>
7where
8    D: DimAPI + DimIntoAPI<D2>,
9    D2: DimAPI,
10{
11    let (storage, layout) = tensor.into_raw_parts();
12    let layout = layout.into_dim::<D2>()?;
13    unsafe { Ok(TensorBase::new_unchecked(storage, layout)) }
14}
15
16/// Convert layout to the other dimension.
17///
18/// This function converts the dimensionality of a tensor's layout to a target dimension type.
19/// No data is copied; only the layout representation is modified.
20///
21/// # Parameters
22///
23/// - `tensor`: [`&TensorAny<R, T, B, D>`](TensorAny)
24///
25///   - The input tensor.
26///
27/// - generic parameter `D2`: [`DimAPI`]
28///
29///   - Target dimension type.
30///   - [`IxD`] or [`IxDyn`] (equilvalent to [`Vec<usize>`]) can be used for dynamic dimension.
31///   - [`Ix<N>`] (given `const N: usize`, equilvalent to [`[usize; N]`](https://doc.rust-lang.org/core/primitive.array.html))
32///     can be used for static dimension.
33///   - Dynamic dimensionality is usually more preferred for general use cases, while static
34///     dimensionality is more suitable for performance-critical code, especially frequent indexing
35///     and non-contiguous memory access.
36///
37/// # Returns
38///
39/// - [`TensorView<'_, T, B, D2>`](TensorView)
40///
41///   - A view of the input tensor with the layout converted to the target dimension type.
42///   - The underlying data is not copied; only the layout of the view is modified.
43///   - If you want to convert the tensor itself (taking the ownership instead of returning view),
44///     use [`into_dim`](TensorAny::into_dim) instead.
45///
46/// # Examples
47///
48/// In most cases, RSTSR will generate dynamic dimension ([`IxD`]) in most cases, including indexing
49/// [`slice`](slice()), reshaping [`reshape`], creation [`asarray`].
50///
51/// You can debug print tensor or it's layout to verify the dimensionality, or call `const_ndim` to
52/// check whether the dimension is static or dynamic.
53///
54/// ```rust
55/// use rstsr::prelude::*;
56/// let a = rt::arange(6).into_shape([2, 3]); // shape: (2, 3), IxD
57/// println!("a: {:?}", a);
58/// // `None` here indicates dynamic dimension
59/// assert_eq!(a.shape().const_ndim(), None);
60/// ```
61///
62/// You can convert the dimension to static dimension by associate method:
63///
64/// ```rust
65/// # use rstsr::prelude::*;
66/// # let a = rt::arange(6).into_shape([2, 3]); // shape: (2, 3), IxD
67/// let b = a.to_dim::<Ix2>(); // shape: (2, 3), Ix2
68/// assert_eq!(b.shape().const_ndim(), Some(2));
69/// ```
70///
71/// You can use `.to_dim::<IxD>()` or `.to_dyn()` to convert back to dynamic dimension:
72///
73/// ```rust
74/// # use rstsr::prelude::*;
75/// # let a = rt::arange(6).into_shape([2, 3]); // shape: (2, 3), IxD
76/// # let b = a.to_dim::<Ix2>(); // shape: (2, 3), Ix2
77/// let c = b.to_dyn(); // shape: (2, 3), IxD
78/// assert_eq!(c.shape().const_ndim(), None);
79/// ```
80///
81/// # Panics
82///
83/// - The shape of the tensor is not compatible with the target dimension type.
84///
85/// ```rust,should_panic
86/// use rstsr::prelude::*;
87/// let a = rt::arange(6).into_shape([2, 3]); // shape: (2, 3), IxD
88/// let b = a.to_dim::<Ix3>(); // shape: (2, 3), Ix3, panics
89/// ```
90///
91/// # See also
92///
93/// ## Similar functions from other crates/libraries
94///
95/// - ndarray: [`into_dimensionality`](https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#method.into_dimensionality)
96/// - ndarray: [`into_dyn`](https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#method.into_dyn)
97///
98/// ## Variants of this function
99///
100/// - [`to_dim`] / [`to_dim_f`]: Returning a view.
101/// - [`into_dim`] / [`into_dim_f`]: Consuming version.
102/// - [`to_dyn`]: Convert to dynamic dimension, returning a view (infallable by definition).
103/// - [`into_dyn`]: Convert to dynamic dimension, consuming version (infallible by definition).
104/// - Associated methods on [`TensorAny`]:
105///
106///   - [`TensorAny::to_dim`] / [`TensorAny::to_dim_f`]
107///   - [`TensorAny::into_dim`] / [`TensorAny::into_dim_f`]
108///   - [`TensorAny::to_dyn`]
109///   - [`TensorAny::into_dyn`]
110pub fn to_dim<R, T, B, D, D2>(tensor: &TensorAny<R, T, B, D>) -> TensorView<'_, T, B, D2>
111where
112    D: DimAPI,
113    D2: DimAPI,
114    D: DimIntoAPI<D2>,
115    R: DataAPI<Data = B::Raw>,
116    B: DeviceAPI<T>,
117{
118    into_dim_f(tensor.view()).rstsr_unwrap()
119}
120
121/// Convert layout to the other dimension.
122///
123/// See also [`to_dim`].
124pub fn to_dim_f<R, T, B, D, D2>(tensor: &TensorAny<R, T, B, D>) -> Result<TensorView<'_, T, B, D2>>
125where
126    D: DimAPI,
127    D2: DimAPI,
128    D: DimIntoAPI<D2>,
129    R: DataAPI<Data = B::Raw>,
130    B: DeviceAPI<T>,
131{
132    into_dim_f(tensor.view())
133}
134
135/// Convert layout to the other dimension.
136///
137/// See also [`to_dim`].
138pub fn into_dim<S, D, D2>(tensor: TensorBase<S, D>) -> TensorBase<S, D2>
139where
140    D: DimAPI,
141    D2: DimAPI,
142    D: DimIntoAPI<D2>,
143{
144    into_dim_f(tensor).rstsr_unwrap()
145}
146
147/// Convert layout to the dynamic dimension [`IxD`].
148///
149/// See also [`to_dim`].
150pub fn to_dyn<R, T, B, D>(tensor: &TensorAny<R, T, B, D>) -> TensorView<'_, T, B, IxD>
151where
152    D: DimAPI,
153    R: DataAPI<Data = B::Raw>,
154    B: DeviceAPI<T>,
155{
156    into_dim_f(tensor.view()).rstsr_unwrap()
157}
158
159/// Convert layout to the dynamic dimension [`IxD`].
160///
161/// See also [`to_dim`].
162pub fn into_dyn<S, D>(tensor: TensorBase<S, D>) -> TensorBase<S, IxD>
163where
164    D: DimAPI,
165{
166    into_dim_f(tensor).rstsr_unwrap()
167}
168
169impl<R, T, B, D> TensorAny<R, T, B, D>
170where
171    D: DimAPI,
172    R: DataAPI<Data = B::Raw>,
173    B: DeviceAPI<T>,
174{
175    /// Convert layout to the other dimension.
176    ///
177    /// See also [`to_dim`].
178    pub fn to_dim<D2>(&self) -> TensorView<'_, T, B, D2>
179    where
180        D2: DimAPI,
181        D: DimIntoAPI<D2>,
182    {
183        to_dim(self)
184    }
185
186    /// Convert layout to the other dimension.
187    ///
188    /// See also [`to_dim`].
189    pub fn to_dim_f<D2>(&self) -> Result<TensorView<'_, T, B, D2>>
190    where
191        D2: DimAPI,
192        D: DimIntoAPI<D2>,
193    {
194        to_dim_f(self)
195    }
196
197    /// Convert layout to the other dimension.
198    ///
199    /// See also [`to_dim`].
200    pub fn into_dim<D2>(self) -> TensorAny<R, T, B, D2>
201    where
202        D2: DimAPI,
203        D: DimIntoAPI<D2>,
204    {
205        into_dim(self)
206    }
207
208    /// Convert layout to the other dimension.
209    ///
210    /// See also [`to_dim`].
211    pub fn into_dim_f<D2>(self) -> Result<TensorAny<R, T, B, D2>>
212    where
213        D2: DimAPI,
214        D: DimIntoAPI<D2>,
215    {
216        into_dim_f(self)
217    }
218
219    /// Convert layout to the dynamic dimension [`IxD`].
220    ///
221    /// See also [`to_dim`].
222    pub fn to_dyn(&self) -> TensorView<'_, T, B, IxD> {
223        to_dyn(self)
224    }
225
226    /// Convert layout to the dynamic dimension [`IxD`].
227    ///
228    /// See also [`to_dim`].
229    pub fn into_dyn(self) -> TensorAny<R, T, B, IxD> {
230        into_dyn(self)
231    }
232}