1use crate::dimension::IntoDimension;
2use crate::order::Order;
3use crate::Dimension;
4
5#[derive(Copy, Clone, Debug)]
9pub struct Shape<D>
10{
11 pub(crate) dim: D,
13 pub(crate) strides: Strides<Contiguous>,
15}
16
17#[derive(Copy, Clone, Debug)]
18pub(crate) enum Contiguous {}
19
20impl<D> Shape<D>
21{
22 pub(crate) fn is_c(&self) -> bool
23 {
24 matches!(self.strides, Strides::C)
25 }
26}
27
28#[derive(Copy, Clone, Debug)]
30pub struct StrideShape<D>
31{
32 pub(crate) dim: D,
33 pub(crate) strides: Strides<D>,
34}
35
36impl<D> StrideShape<D>
37where D: Dimension
38{
39 pub fn raw_dim(&self) -> &D
41 {
42 &self.dim
43 }
44 pub fn size(&self) -> usize
46 {
47 self.dim.size()
48 }
49}
50
51#[derive(Copy, Clone, Debug)]
53pub(crate) enum Strides<D>
54{
55 C,
57 F,
59 Custom(D),
61}
62
63impl<D> Strides<D>
64{
65 pub(crate) fn strides_for_dim(self, dim: &D) -> D
67 where D: Dimension
68 {
69 match self {
70 Strides::C => dim.default_strides(),
71 Strides::F => dim.fortran_strides(),
72 Strides::Custom(c) => {
73 debug_assert_eq!(
74 c.ndim(),
75 dim.ndim(),
76 "Custom strides given with {} dimensions, expected {}",
77 c.ndim(),
78 dim.ndim()
79 );
80 c
81 }
82 }
83 }
84
85 #[inline]
86 pub(crate) fn is_custom(&self) -> bool
87 {
88 matches!(*self, Strides::Custom(_))
89 }
90}
91
92pub trait ShapeBuilder
98{
99 type Dim: Dimension;
101
102 type Strides;
104
105 fn into_shape_with_order(self) -> Shape<Self::Dim>;
107
108 fn f(self) -> Shape<Self::Dim>;
110
111 fn set_f(self, is_f: bool) -> Shape<Self::Dim>;
113
114 fn strides(self, strides: Self::Strides) -> StrideShape<Self::Dim>;
116}
117
118impl<D> From<D> for Shape<D>
119where D: Dimension
120{
121 fn from(dimension: D) -> Shape<D>
123 {
124 dimension.into_shape_with_order()
125 }
126}
127
128impl<T, D> From<T> for StrideShape<D>
129where
130 D: Dimension,
131 T: ShapeBuilder<Dim = D>,
132{
133 fn from(value: T) -> Self
134 {
135 let shape = value.into_shape_with_order();
136 let st = if shape.is_c() { Strides::C } else { Strides::F };
137 StrideShape {
138 strides: st,
139 dim: shape.dim,
140 }
141 }
142}
143
144impl<T> ShapeBuilder for T
145where T: IntoDimension
146{
147 type Dim = T::Dim;
148 type Strides = T;
149 fn into_shape_with_order(self) -> Shape<Self::Dim>
150 {
151 Shape {
152 dim: self.into_dimension(),
153 strides: Strides::C,
154 }
155 }
156 fn f(self) -> Shape<Self::Dim>
157 {
158 self.set_f(true)
159 }
160 fn set_f(self, is_f: bool) -> Shape<Self::Dim>
161 {
162 self.into_shape_with_order().set_f(is_f)
163 }
164 fn strides(self, st: T) -> StrideShape<Self::Dim>
165 {
166 self.into_shape_with_order().strides(st.into_dimension())
167 }
168}
169
170impl<D> ShapeBuilder for Shape<D>
171where D: Dimension
172{
173 type Dim = D;
174 type Strides = D;
175
176 fn into_shape_with_order(self) -> Shape<D>
177 {
178 self
179 }
180
181 fn f(self) -> Self
182 {
183 self.set_f(true)
184 }
185
186 fn set_f(mut self, is_f: bool) -> Self
187 {
188 self.strides = if !is_f { Strides::C } else { Strides::F };
189 self
190 }
191
192 fn strides(self, st: D) -> StrideShape<D>
193 {
194 StrideShape {
195 dim: self.dim,
196 strides: Strides::Custom(st),
197 }
198 }
199}
200
201impl<D> Shape<D>
202where D: Dimension
203{
204 pub fn raw_dim(&self) -> &D
206 {
207 &self.dim
208 }
209 pub fn size(&self) -> usize
211 {
212 self.dim.size()
213 }
214}
215
216pub trait ShapeArg
225{
226 type Dim: Dimension;
228
229 fn into_shape_and_order(self) -> (Self::Dim, Option<Order>);
231}
232
233impl<T> ShapeArg for T
234where T: IntoDimension
235{
236 type Dim = T::Dim;
237
238 fn into_shape_and_order(self) -> (Self::Dim, Option<Order>)
239 {
240 (self.into_dimension(), None)
241 }
242}
243
244impl<T> ShapeArg for (T, Order)
245where T: IntoDimension
246{
247 type Dim = T::Dim;
248
249 fn into_shape_and_order(self) -> (Self::Dim, Option<Order>)
250 {
251 (self.0.into_dimension(), Some(self.1))
252 }
253}