1use std::mem::MaybeUninit;
31use std::iter::Iterator;
32
33use crate::base::*;
34
35use std::ops::{ Add, BitOr };
36use typenum::{
37 IsLessOrEqual, Sum, LeEq, True, U1
38};
39
40#[cfg(doc)] use crate::algebra::*;
41#[cfg(doc)] use crate::subspace::*;
42
43pub struct DefaultAllocator;
45
46pub type Allocate<M> = <DefaultAllocator as Alloc<M>>::Buffer;
48
49pub type AllocateBlade<T,N,G> = <T as AllocBlade<N,G>>::Buffer;
51
52pub type AllocateEven<T,N> = <T as AllocEven<N>>::Buffer;
54
55pub type AllocateOdd<T,N> = <T as AllocOdd<N>>::Buffer;
57
58pub type AllocateMultivector<T,N> = <T as AllocMultivector<N>>::Buffer;
60
61pub trait Alloc<M> {
75
76 type Scalar: Sized;
78
79 type Shape: Copy;
81
82 type Buffer: Storage<Self::Scalar, Uninit=Self::Uninit>;
84
85 type Uninit: UninitStorage<Self::Scalar, Init=Self::Buffer>;
87
88 fn shape(this: &M) -> Self::Shape;
90 fn uninit(shape: Self::Shape) -> Self::Uninit;
92
93 unsafe fn assume_init(uninit: Self::Uninit) -> M;
97
98}
99
100pub trait AllocBlade<N:Dim,G:Dim>: Sized {
102 type Buffer: BladeStorage<Self,N,G>;
103}
104
105pub trait AllocEven<N:Dim>: Sized {
107 type Buffer: EvenStorage<Self,N>;
108}
109
110pub trait AllocOdd<N:Dim>: Sized {
112 type Buffer: OddStorage<Self,N>;
113}
114
115pub trait AllocVersor<N:Dim>: AllocEven<N> + AllocOdd<N> {}
117impl<T:AllocEven<N>+AllocOdd<N>, N:Dim> AllocVersor<N> for T {}
118
119pub trait AllocMultivector<N:Dim>: Sized {
121 type Buffer: MultivectorStorage<Self,N>;
122}
123
124pub trait AllocSimpleBlade<N:Dim,G:Dim>: AllocBlade<N,G> {}
139
140impl<T:AllocBlade<Dyn,Const<0>>> AllocSimpleBlade<Dyn,Const<0>> for T {}
141impl<T:AllocBlade<Dyn,Const<1>>> AllocSimpleBlade<Dyn,Const<1>> for T {}
142impl<T:AllocBlade<N,G>,N:Dim,G:Dim> AllocSimpleBlade<N,G> for T where
143 N: DimName+ToTypenum,
145 G: DimName+ToTypenum,
146
147 G::Typenum: Add<U1> + IsLessOrEqual<U1>,
149 N::Typenum: IsLessOrEqual<Sum<G::Typenum,U1>>,
150
151 LeEq<G::Typenum, U1>: BitOr<LeEq<N::Typenum, Sum<G::Typenum,U1>>, Output=True>
153{}
154
155impl<T, const N: usize> AllocBlade<Const<N>, Dyn> for T {
156 type Buffer = DynBladeStorage<T, Const<N>, Dyn>;
157}
158
159impl<T, const G: usize> AllocBlade<Dyn, Const<G>> for T {
160 type Buffer = DynBladeStorage<T, Dyn, Const<G>>;
161}
162
163impl<T> AllocBlade<Dyn, Dyn> for T {
164 type Buffer = DynBladeStorage<T, Dyn, Dyn>;
165}
166
167impl<T> AllocEven<Dyn> for T {
168 type Buffer = DynEvenStorage<T, Dyn>;
169}
170
171impl<T> AllocOdd<Dyn> for T {
172 type Buffer = DynOddStorage<T, Dyn>;
173}
174
175impl<T> AllocMultivector<Dyn> for T {
176 type Buffer = DynMultivectorStorage<T, Dyn>;
177}
178
179#[inline(always)]
180fn uninit_array<T, const L: usize>() -> [MaybeUninit<T>; L] {
181 unsafe {
183 MaybeUninit::uninit().assume_init()
185 }
186}
187
188#[inline(always)]
189fn array_from_iter<T, I: IntoIterator<Item=T>, const L: usize>(iter:I, kind:&str) -> [T;L] {
190 let mut uninit: [MaybeUninit<T>;L] = uninit_array();
192
193 let mut count = 0;
195 for (i, x) in (0..L).zip(iter) {
196 uninit[i] = MaybeUninit::new(x);
197 count = i+1;
198 }
199
200 if count!=L {
202 panic!("Not enough elements to fill {}", kind);
203 }
204
205 unsafe { <[MaybeUninit<T>;L] as UninitStorage<T>>::assume_init(uninit) }
206}
207
208macro_rules! impl_alloc{
209
210 ($n:literal $($N:literal)*; $($G:literal)*; @$cmd:ident $($pairs:tt)*) => {
211 impl_alloc!($($N)*; $($G)*; @$cmd $($pairs)* $(($n, $G))*);
212
213 impl_alloc!($n @$cmd);
214
215 };
216
217 ($N:literal @tests) => {
219 assert_eq!(
220 std::mem::size_of::<AllocateEven<f32, Const<$N>>>(),
221 std::mem::size_of::<f32>() * even_elements($N)
223 );
224
225 assert_eq!(
226 std::mem::size_of::<AllocateOdd<f32, Const<$N>>>(),
227 std::mem::size_of::<f32>() * odd_elements($N)
229 );
230
231 assert_eq!(
232 std::mem::size_of::<AllocateMultivector<f32, Const<$N>>>(),
233 std::mem::size_of::<f32>() * 2usize.pow($N)
234 );
235 };
236
237 ($N:literal @impl) => {
238 impl<T> AllocEven<Const<$N>> for T {
239 type Buffer = [T; even_elements($N)];
240 }
241
242 unsafe impl<T> EvenStorage<T, Const<$N>> for [T; even_elements($N) ] {
243 fn dim(&self) -> Const<$N> { Const::<$N> }
244 fn uninit(_: Const<$N>,) -> Self::Uninit { uninit_array() }
245 fn from_iterator<I:IntoIterator<Item=T>>(_: Const<$N>, iter: I) -> Self {
246 array_from_iter(iter, "value")
247 }
248 }
249
250 impl<T> AllocOdd<Const<$N>> for T {
251 type Buffer = [T; odd_elements($N)];
252 }
253
254 unsafe impl<T> OddStorage<T, Const<$N>> for [T; odd_elements($N) ] {
255 fn dim(&self) -> Const<$N> { Const::<$N> }
256 fn uninit(_: Const<$N>,) -> Self::Uninit { uninit_array() }
257 fn from_iterator<I:IntoIterator<Item=T>>(_: Const<$N>, iter: I) -> Self {
258 array_from_iter(iter, "value")
259 }
260 }
261
262 impl<T> AllocMultivector<Const<$N>> for T {
263 type Buffer = [T; 2usize.pow($N)];
264 }
265
266 unsafe impl<T> MultivectorStorage<T, Const<$N>> for [T; 2usize.pow($N)] {
267 fn dim(&self) -> Const<$N> { Const::<$N> }
268 fn uninit(_: Const<$N>,) -> Self::Uninit { uninit_array() }
269 fn from_iterator<I:IntoIterator<Item=T>>(_: Const<$N>, iter: I) -> Self {
270 array_from_iter(iter, "multivector")
271 }
272 }
273
274 };
275
276 (; $($_G:literal)*; @impl $(($N:literal, $G:literal))*) => {
277 $(
278 impl<T> AllocBlade<Const<$N>, Const<$G>> for T {
279 type Buffer = [T; binom($N, $G)];
280 }
281
282 unsafe impl<T> BladeStorage<T, Const<$N>, Const<$G>> for [T; binom($N, $G)] {
283 fn dim(&self) -> Const<$N> { Const::<$N> }
284 fn grade(&self) -> Const<$G> { Const::<$G> }
285
286 fn uninit(_: Const<$N>, _: Const<$G>) -> Self::Uninit { uninit_array() }
287
288 fn from_iterator<I:IntoIterator<Item=T>>(_: Const<$N>, _: Const<$G>, iter: I) -> Self {
289 array_from_iter(iter, "blade")
290 }
291 }
292
293 )*
294 };
295
296 (; $($_G:literal)*; @tests $(($N:literal, $G:literal))*) => {
298 $(
299 assert_eq!(
300 std::mem::size_of::<AllocateBlade<f32, Const<$N>, Const<$G>>>(),
301 std::mem::size_of::<f32>() * binom($N, $G)
302 );
303 )*
304 };
305}
306
307impl_alloc!(
308 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; @impl
309);
310
311#[test]
312#[cfg(test)]
313fn buffer_sizes() {
314 impl_alloc!(
315 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; @tests
316 );
317}