container_broadcast/
broadcast.rs

1//#![feature(const_generics, const_evaluatable_checked)]
2
3use crate::dimutils;
4
5
6/// Implement by specifying the const DIM to give your implementation a dimension.
7pub trait TensorDimension {
8    const DIM : usize;
9    const ISSCALAR : bool = Self::DIM == 0;
10    fn is_scalar(&self) -> bool {Self::ISSCALAR}
11}
12
13
14
15///  Expresses tensor-like objects with a size. Due to current compiler constraints, takes the dimension as an argument 
16///  in addition to it being an associated type, to avoid internal compiler errors in use.
17pub trait TensorSize<const DIM:usize> : TensorDimension {
18    fn size(&self) -> [usize;DIM];
19
20    fn inbounds(&self,index : [usize;DIM]) -> bool {
21        index.iter().zip(self.size().iter()).all(|(i,s)| i < s)   
22    }
23
24    /// Returns an iterator over all valid indices.
25    fn eachindex(&self) -> dimutils::EachIndex<DIM> {
26        assert!(Self::VALIDDIMS, "Invalid dimensions entered in Trait implementation."); // These asserts can be eliminated with more advanced
27        dimutils::ndim_iterator(self.size())
28    }
29
30    /// If this is false, you have an invalid implementation.
31    const VALIDDIMS : bool = DIM == Self::DIM;
32}
33
34/// The main trait of this crate. Somehat like iterator, is effectively a lazy multidimensional array-like object
35/// instead of a lazy sequence.
36/// You can map over functions, zip them, take cartesian products, etc etc in a way that does
37/// not erase structure, and produces another object with random access indexing unlike iterators.
38pub trait Broadcastable<const DIM : usize> : TensorSize<DIM> + Sized {
39    type Element;
40
41    /// This should return none iff the default
42    /// inbounds method returns false.
43    fn bget(&self, index:[usize;DIM]) -> Option<Self::Element>;
44
45    /// Takes indices modulo size. Useful for periodic shifts of indices.
46    fn mod_bget(&self,index:[isize;DIM]) -> Self::Element {
47        self.bget(dimutils::modular_index(index,self.size())).expect("Broken contract in Broadcast impl. Modular access out of bounds.")
48    }
49
50    /// Writes the contents of the Broadcastable to a receiver, such as an actual (multidimensional) array.
51    fn feedto(&self,receiver :&mut impl BroadcastReceiver<DIM,Element=Self::Element>) -> Option<()>{
52        receiver.receive(self)
53    }
54
55    /// Returns an object with the provided size. If NEWDIM > Self::DIM, the additional indices are ignored.
56    /// All entries of size input must be either equal to the size of input, except for entries where the original size was 1.
57    fn lazy_updim<const NEWDIM : usize>(&self, size : [usize;NEWDIM] ) -> LazyUpdim<Self,DIM,NEWDIM> 
58    {
59        assert!(Self::VALIDDIMS, "Invalid dimensions entered in Trait implementation."); // These asserts can be eliminated with more advanced
60        assert!(NEWDIM >= DIM, "Updimmed tensor cannot have fewer indices than the initial one."); // const generic bounds on nightly. ( )
61        LazyUpdim {size,reference:&self}
62    }
63
64    /// The main way to create multidimensional arrays with this crate, 
65    /// but can resize any broadcastable. Resized broadcastables must have the
66    /// same number of elements as the old one. Preserves iteration order.
67    /// Reshapes a broadcastable by linearizing and delinearizing indices.
68    fn reshaped<const NEWDIM : usize>(self,size: [usize;NEWDIM]) -> ReShaped<Self,NEWDIM,DIM> {
69        assert!(Self::VALIDDIMS, "Invalid dimensions entered in Trait implementation."); // These asserts can be eliminated with more advanced
70        ReShaped {underlying : self,index_multipliers:dimutils::linearization_coeffs(size),size}
71    }
72
73    /// Provides a more flexible but less safe way to reshape a broadcastable. 
74    /// Useful for slicing and dicing arrays and broadcastables, taking diagonals, etc etc.
75    fn mapindex<F:Fn([usize;M],[usize;M]) -> [usize;DIM],const M : usize>(&self,indexclosure:F,sizeclosure : impl Fn([usize;DIM]) -> [usize;M] ) 
76    -> MapIndex<Self,F,DIM,M>
77    {
78        assert!(Self::VALIDDIMS, "Invalid dimensions entered in Trait implementation."); // These asserts can be eliminated with more advanced
79        MapIndex {reference: self,indexclosure,size:sizeclosure(self.size())}
80    }
81
82    /// Returns a new broadcast which is periodically offset by offset.
83    fn offset_mod(&self,offset : [isize;DIM]) -> OffsetBroadcast<Self,DIM> {
84        assert!(Self::VALIDDIMS, "Invalid dimensions entered in Trait implementation."); // These asserts can be eliminated with more advanced
85        OffsetBroadcast {underlying:self,offset}
86    }
87
88
89    /// Elements of returned broadcastable are the output of the provided closure, 
90    /// applied to the input broadcastable.
91    fn bmap<T,F :Fn(Self::Element) -> T>(&self,foo : F) -> BMap<T,Self,F,DIM>{
92        assert!(Self::VALIDDIMS, "Invalid dimensions entered in Trait implementation.");
93        BMap {reference:self,closure : foo}
94    }
95
96    /// For inputs whose elements are references, clones them.
97    fn bcloned(self) -> BCloned<Self,DIM> {
98        assert!(Self::VALIDDIMS, "Invalid dimensions entered in Trait implementation."); // These asserts can be eliminated with more advanced
99        BCloned {underlying:self}
100    }
101    
102    /// Unique operation not found in Iterators. If the dimensions of the two broadcastable, zips them. 
103    /// If not, will lazy_updim all inputs to the same size. As such, can also provide cartesian or tensor products depending on input.
104    /// NEW CONSTRAINT IN v0.0.6: N must be smaller than DIM, CHECKED AT RUNTIME. The argument with higher Self::DIM must be first. 
105    /// This is partly to eliminate use of nightly features, and because the Rust type system often cannot prove equality. 
106    fn broadcast2<'a,'b,T : Broadcastable<N>,const N : usize >(&'a self,foo: &'b T) 
107        -> Broadcast2<LazyUpdim<'a,Self,DIM,DIM>,LazyUpdim<'b,T,N,DIM>,DIM> 
108    {
109        assert!(Self::VALIDDIMS, "Invalid dimensions entered in Trait implementation."); // These asserts can be eliminated with more advanced
110        assert!(DIM >= N, "To keep type signatures inferrable and to eliminate nightly features, the dimension of the first argument must be greater than or equal to the dimension of the second.");
111        let commondims : [usize;DIM] = dimutils::commondims_first(self.size(),foo.size()).expect("F error handling");
112        Broadcast2 {first : self.lazy_updim(commondims),second : foo.lazy_updim(commondims)}
113    }
114
115    /// Takes a broadcastable and returns an iterator over its elements.
116    fn bc_iter(&self) -> BroadcastIterator<Self,DIM> {
117        assert!(Self::VALIDDIMS, "Invalid dimensions entered in Trait implementation."); // These asserts can be eliminated with more advanced
118        BroadcastIterator {reference:self,state : self.eachindex()}
119    }
120}
121
122/// Trait that emulates write access to reshaped arrays.
123pub trait BroadcastReceiver<const DIM : usize> : TensorSize<DIM> + Sized {
124    type Element;
125    fn bget_mut<'a>(&'a mut self, index: [usize;DIM]) -> Option<&'a mut Self::Element>;
126
127    fn receive(&mut self, broadcast: &impl Broadcastable<DIM,Element=Self::Element>) -> Option<()> {
128        if self.size() != broadcast.size() {return None};
129        for index in self.eachindex() {
130            *(self.bget_mut(index)?) = broadcast.bget(index)?;
131        }
132        Some(())
133    }
134    // TODO: properly review the implementation of iter_mut, which is unsafe. This should need GATs to be safe.
135    /// To be safe, the BroadcastReceiver must NOT alias bget_mut to the same underlying field for different inputs.
136    /// You may implement a safe iter_mut method using this on any receiver where that invariant is preserved.
137    /// If in doubt, use eachindex + bget_mut for a safe solution.
138    unsafe fn bc_iter_mut<'a>(&'a mut self) -> BroadcastIterMut<'a,Self,DIM> {
139        BroadcastIterMut {reference : self.into() ,state: self.eachindex(),_marker: core::marker::PhantomData}
140    }
141}
142
143
144/// Return type of bc_iter.
145pub struct BroadcastIterator<'a,T : Broadcastable<DIM>,const DIM : usize> {
146    reference : &'a T,
147    state : dimutils::EachIndex<DIM>,
148}
149
150impl<'a,T : Broadcastable<DIM>,const DIM : usize> Iterator for BroadcastIterator<'a,T,DIM> {
151    type Item = T::Element;
152    fn next(&mut self) -> Option<T::Element> {
153        let index = self.state.next()?;
154        self.reference.bget(index)
155    }
156    fn size_hint(&self) -> (usize,Option<usize>){
157        self.state.size_hint()
158    }
159}
160
161impl<'a,T : Broadcastable<DIM>,const DIM : usize> ExactSizeIterator for BroadcastIterator<'a,T,DIM> {}
162impl<'a,T : Broadcastable<DIM>,const DIM : usize> core::iter::FusedIterator for BroadcastIterator<'a,T,DIM> {}
163
164/// Return type of bc_iter_mut.
165pub struct BroadcastIterMut<'a,T : BroadcastReceiver<DIM>,const DIM : usize> {
166    reference : core::ptr::NonNull<T>,
167    state :dimutils::EachIndex<DIM>,
168    _marker: core::marker::PhantomData<&'a mut T>,
169}
170
171impl<'a,T : BroadcastReceiver<DIM>,const DIM : usize> Iterator for BroadcastIterMut<'a,T,DIM> {
172    type Item = &'a mut T::Element;
173    fn next(&mut self) -> Option< &'a mut T::Element> {
174        let index = self.state.next()?;
175        let castreference =  unsafe {self.reference.as_mut::<'a>()};
176        castreference.bget_mut(index)
177    }
178    fn size_hint(&self) -> (usize,Option<usize>){
179        self.state.size_hint()
180    }
181}
182
183
184/// Return type of reshaped.
185#[derive(Clone,Eq,PartialEq,Debug)]
186pub struct ReShaped<T:Broadcastable<M>,const N : usize,const M : usize> {
187    underlying : T,
188    index_multipliers : [usize;N],
189    size : [usize;N]
190}
191
192impl<T:Broadcastable<M>,const N : usize,const M : usize> TensorDimension for ReShaped<T,N,M> {
193    const DIM : usize = N;
194}
195impl<T:Broadcastable<M>,const N : usize,const M : usize> TensorSize<N> for ReShaped<T,N,M> {
196    fn size(&self) -> [usize;N] {self.size}
197}
198impl<T:Broadcastable<M>,const N : usize,const M : usize> Broadcastable<N> for ReShaped<T,N,M> {
199    type Element = T::Element;
200    fn bget(&self,index:[usize;N])-> Option<T::Element> {
201        if !self.inbounds(index) {return None}
202        let linearindex = dimutils::linearize_index(index,self.index_multipliers);
203        let innerindex = dimutils::delinearize_index(linearindex,self.underlying.size());
204        self.underlying.bget(innerindex)
205    }
206}
207impl<T:Broadcastable<M> + BroadcastReceiver<M>,const N : usize,const M : usize> BroadcastReceiver<N> for ReShaped<T,N,M> {
208    type Element = <T as BroadcastReceiver<M> >::Element;
209    fn bget_mut(&mut self, index:[usize;N]) -> Option<&mut Self::Element> {
210        if !self.inbounds(index) {return None}
211        let linearindex = dimutils::linearize_index(index,self.index_multipliers);
212        let innerindex = dimutils::delinearize_index(linearindex,self.underlying.size());
213        self.underlying.bget_mut(innerindex)
214    }
215}
216
217impl<'a,T:Broadcastable<M>,const N : usize,const M : usize> IntoIterator for &'a ReShaped<T,N,M> {
218    type Item = T::Element;
219    type IntoIter = BroadcastIterator<'a,ReShaped<T,N,M>,N>;
220    fn into_iter(self) -> Self::IntoIter  {
221        self.bc_iter()
222    }
223}
224impl<T:Broadcastable<M> + BroadcastReceiver<M>,const N : usize,const M : usize> ReShaped<T,N,M> {
225    fn iter(&self) ->  BroadcastIterator<ReShaped<T,N,M>,N> {
226        self.bc_iter()
227    }
228}
229
230
231/// Return type of offset_mod.
232#[derive(Copy,Clone)]
233pub struct OffsetBroadcast<'a,T : Broadcastable<N>,const N : usize> {
234    underlying : &'a T,
235    offset : [isize;N]
236}
237
238impl<'a,T : Broadcastable<N>,const N : usize> TensorDimension for OffsetBroadcast<'a,T,N> {
239    const DIM : usize = N;
240}
241impl<'a,T : Broadcastable<N>,const N : usize> TensorSize<N> for OffsetBroadcast<'a,T,N> {
242    fn size(&self) -> [usize;N] { self.underlying.size()}
243}
244impl<'a,T : Broadcastable<N>,const N : usize> Broadcastable<N> for OffsetBroadcast<'a,T,N> {
245    type Element = T::Element;
246    fn bget(&self,index:[usize;N]) -> Option<T::Element> {
247        let modindex : [isize;N] = array_init::array_init(|i| index[i] as isize + self.offset[i]);
248        Some(self.underlying.mod_bget(modindex))
249    }
250}
251impl<'b,'a,T:Broadcastable<N>,const N : usize> IntoIterator for &'b OffsetBroadcast<'a,T,N> {
252    type Item = T::Element;
253    type IntoIter = BroadcastIterator<'b,OffsetBroadcast<'a,T,N>,N>;
254    fn into_iter(self) -> Self::IntoIter  {
255        self.bc_iter()
256    }
257}
258impl<'a,T : Broadcastable<N>,const N : usize> OffsetBroadcast<'a,T,N> {
259    fn iter(&self) ->  BroadcastIterator<OffsetBroadcast<'a,T,N>,N> {
260        self.bc_iter()
261    }
262}
263
264
265
266
267/// Return type of bcloned.
268pub struct BCloned<T:Broadcastable<N>,const N : usize> {
269    underlying : T,
270}
271
272impl<'a,T:Broadcastable<N>,const N : usize> TensorDimension for BCloned<T,N> {
273    const DIM : usize = T::DIM;
274}
275impl<'a,T:Broadcastable<N>,const N : usize> TensorSize<N> for BCloned<T,N> {
276    fn size(&self) -> [usize;N] {self.underlying.size()}
277}
278impl<'b,T:Broadcastable<N,Element=&'b E>,E : 'b + Clone,const N : usize> Broadcastable<N> for BCloned<T,N> 
279{
280    type Element = E;
281    fn bget(&self,index:[usize;N]) -> Option<Self::Element>  {
282         self.underlying.bget(index).cloned()
283    }
284}
285impl<'a,'b,T:Broadcastable<N,Element=&'b E>,E : Clone + 'a + 'b,const N : usize> IntoIterator for &'a BCloned<T,N> {
286    type Item = E;
287    type IntoIter = BroadcastIterator<'a,BCloned<T,N>,N>;
288    fn into_iter(self) -> Self::IntoIter  {
289        self.bc_iter()
290    }
291}
292
293impl<'b,T:Broadcastable<N,Element=&'b E>,E : 'b + Clone,const N : usize> BCloned<T,N> {
294    fn iter(&self) -> BroadcastIterator<BCloned<T,N>,N>  {
295        self.bc_iter()
296    }
297}
298
299
300/// Return type of mapindex.
301pub struct MapIndex<'a,T:Broadcastable<N>, F : Fn([usize;M],[usize;M]) -> [usize;N] ,const N : usize,const M : usize> {
302    reference : &'a T,
303    indexclosure : F,
304    size : [usize;M],
305}
306
307impl<'a,T:Broadcastable<N>, F : Fn([usize;M],[usize;M]) -> [usize;N] ,const N : usize,const M : usize> TensorDimension for MapIndex<'a,T,F,N,M> {
308    const DIM : usize = M;
309}
310impl<'a,T:Broadcastable<N>, F : Fn([usize;M],[usize;M]) -> [usize;N] ,const N : usize,const M : usize> TensorSize<M> for MapIndex<'a,T,F,N,M> {
311    fn size(&self) -> [usize;M] {self.size}
312}
313impl<'a,T:Broadcastable<N>, F : Fn([usize;M],[usize;M]) -> [usize;N] ,const N : usize,const M : usize> Broadcastable<M> for MapIndex<'a,T,F,N,M> {
314    type Element = T::Element;
315    fn bget(&self,index : [usize;M]) -> Option<T::Element> {
316        if !self.inbounds(index) {return None};
317        let size = self.size;
318        let indexclosure = &self.indexclosure;
319        let newindex : [usize;N] = indexclosure(index,size);
320        self.reference.bget(newindex)
321    }
322}
323
324impl<'b,'a,T:Broadcastable<N>, F : Fn([usize;M],[usize;M]) -> [usize;N] ,const N : usize,const M : usize> IntoIterator for &'b MapIndex<'a,T,F,N,M> {
325    type Item = T::Element;
326    type IntoIter = BroadcastIterator<'b,MapIndex<'a,T,F,N,M>,M>;
327    fn into_iter(self) -> Self::IntoIter  {
328        self.bc_iter()
329    }
330} 
331
332impl<'a,T:Broadcastable<N>, F : Fn([usize;M],[usize;M]) -> [usize;N] ,const N : usize,const M : usize>  MapIndex<'a,T,F,N,M> {
333    pub fn iter(&self) -> BroadcastIterator<MapIndex<'a,T,F,N,M>,M> {
334        self.into_iter()
335    }
336}
337
338
339
340/// Return type of broadcast2.
341pub struct Broadcast2<A : Broadcastable<N>,B : Broadcastable<N>, const N : usize> {
342    first: A,
343    second: B
344}
345
346impl<A : Broadcastable<N>,B : Broadcastable<N>, const N : usize> TensorDimension for Broadcast2<A,B,N> {
347    const DIM : usize = N;
348}
349impl<A : Broadcastable<N>,B : Broadcastable<N>, const N : usize> TensorSize<N> for Broadcast2<A,B,N> {
350    fn size(&self) -> [usize;N] {
351        self.first.size()
352    }
353}
354impl<A : Broadcastable<N>,B : Broadcastable<N>, const N : usize> Broadcastable<N> for Broadcast2<A,B,N> {
355    type Element = (A::Element,B::Element);
356    fn bget(&self, index:[usize;N]) -> Option<Self::Element> {
357        Some((self.first.bget(index)?,self.second.bget(index)?))
358    }
359}
360
361impl<'b,A : Broadcastable<N>,B : Broadcastable<N>, const N : usize> IntoIterator for &'b Broadcast2<A,B,N> {
362    type Item = (A::Element,B::Element);
363    type IntoIter = BroadcastIterator<'b, Broadcast2<A,B,N> ,N>;
364    fn into_iter(self) -> Self::IntoIter  {
365        self.bc_iter()
366    }
367}
368impl<A : Broadcastable<N>,B : Broadcastable<N>, const N : usize> Broadcast2<A,B,N> {
369    pub fn iter(&self) -> BroadcastIterator<Broadcast2<A,B,N> ,N> {
370        self.bc_iter()
371    }
372}
373
374
375/// Jointly broadcasts an arbitrary number of Broadcastables of the same type together.
376pub fn broadcast_k<'a,A : Broadcastable<N>, const K : usize, const N : usize>(bcables : [&'a A;K]) -> BroadcastK<LazyUpdim<'a,A,N,N>,N,K> {
377    let mut size : [usize;N] = [1;N];
378    for &broadcastable in bcables.iter() {
379        size = dimutils::commondims_samedims(size,broadcastable.size()).expect("F error handling")
380    }
381    BroadcastK {factors: bcables.map(|x| x.lazy_updim(size)) }
382}
383
384
385/// Return type of broadcastK.
386pub struct BroadcastK<A : Broadcastable<N>, const N : usize,const K : usize> {
387    factors : [A;K]
388}
389impl<A : Broadcastable<N>, const N : usize,const K : usize> TensorDimension for BroadcastK<A,N,K> {
390    const DIM : usize = N;
391}
392impl<A : Broadcastable<N>, const N : usize,const K : usize> TensorSize<N> for BroadcastK<A,N,K> {
393    fn size(&self) -> [usize;N] {
394        self.factors[1].size()
395    }
396}
397impl<A : Broadcastable<N>, const N : usize,const K : usize> Broadcastable<N> for BroadcastK<A,N,K> {
398    type Element = [A::Element;K];
399    fn bget(&self, index:[usize;N]) -> Option<Self::Element> {
400        if self.inbounds(index) {
401            Some(self.factors.each_ref().map(|x|x.bget(index).expect("Factors of broadcast_k have invalid sizes!")))
402        } else {None}
403    }
404}
405impl<'b ,A : Broadcastable<N>, const N : usize,const K : usize> IntoIterator for &'b BroadcastK<A,N,K> {
406    type Item = [A::Element;K];
407    type IntoIter = BroadcastIterator<'b, BroadcastK<A,N,K> ,N>;
408    fn into_iter(self) -> Self::IntoIter  {
409        self.bc_iter()
410    }
411}
412impl<'b ,A : Broadcastable<N>, const N : usize,const K : usize> BroadcastK<A,N,K> {
413    pub fn iter(&self) -> BroadcastIterator<BroadcastK<A,N,K> ,N> {
414        self.bc_iter()
415    }
416}
417
418
419/// Return type of lazy_updim.
420#[derive(Copy,Clone)]
421pub struct LazyUpdim<'a,T : Broadcastable<OLDDIM>,const OLDDIM : usize, const DIM : usize> {
422    size : [usize;DIM],
423    reference : &'a T
424}
425
426impl<'a,T : Broadcastable<OLDDIM>,const OLDDIM : usize,const DIM : usize> TensorDimension for LazyUpdim<'a,T,OLDDIM,DIM> {
427    const DIM : usize = DIM;
428}
429impl<'a,T : Broadcastable<OLDDIM>,const OLDDIM : usize,const DIM : usize> TensorSize<DIM> for LazyUpdim<'a,T,OLDDIM,DIM> {
430    fn size(&self) -> [usize;DIM] {self.size}
431}
432impl<'a,T : Broadcastable<OLDDIM>,const OLDDIM : usize,const DIM : usize>  Broadcastable<DIM>  for LazyUpdim<'a,T,OLDDIM,DIM> {
433    type Element = T::Element;
434    fn bget(&self,index:[usize;DIM]) -> Option<Self::Element> {
435        assert!(DIM >= OLDDIM);
436        if !self.inbounds(index) {return None}
437        let size = self.size();
438        let newindex : [usize;OLDDIM] = array_init::array_init(|i| if size[i] > 1 {index[i]} else {0});
439        self.reference.bget(newindex)
440    }
441}
442
443impl<'b,'a,T : Broadcastable<OLDDIM>,const OLDDIM : usize,const DIM : usize> IntoIterator for &'b LazyUpdim<'a,T,OLDDIM,DIM> {
444    type Item = T::Element;
445    type IntoIter = BroadcastIterator<'b,LazyUpdim<'a,T,OLDDIM,DIM>,DIM>;
446    fn into_iter(self) -> Self::IntoIter  {
447        self.bc_iter()
448    }
449}
450
451impl<'a,T : Broadcastable<OLDDIM>,const OLDDIM : usize,const DIM : usize> LazyUpdim<'a,T,OLDDIM,DIM> {
452    pub fn iter(&self) ->  BroadcastIterator<LazyUpdim<'a,T,OLDDIM,DIM>,DIM>  {
453        self.bc_iter()
454    }
455}
456
457
458/// Return type of bmap.
459pub struct BMap<'a,R, T : Broadcastable<DIM>, F :  Fn(T::Element) -> R  , const DIM: usize> {
460    reference : &'a T,
461    closure : F
462}
463
464impl<'a,R, T : Broadcastable<DIM>, F :  Fn(T::Element) -> R  , const DIM: usize> TensorDimension for BMap<'a,R,T,F,DIM> {
465    const DIM : usize = DIM;
466}
467impl<'a,R, T : Broadcastable<DIM>, F :  Fn(T::Element) -> R  , const DIM: usize> TensorSize<DIM> for BMap<'a,R,T,F,DIM> {
468    fn size(&self) -> [usize;DIM] {self.reference.size()}
469}
470impl<'a,R, T : Broadcastable<DIM>, F :  Fn(T::Element) -> R  , const DIM: usize> Broadcastable<DIM> for BMap<'a,R,T,F,DIM> {
471    type Element = R;
472    fn bget(&self,index:[usize;DIM]) -> Option<Self::Element> {
473        self.reference.bget(index).map(&self.closure)
474    }
475}
476
477impl<'b,'a,R, T : Broadcastable<DIM>, F :  Fn(T::Element) -> R  , const DIM: usize> IntoIterator for &'b BMap<'a,R,T,F,DIM> {
478    type Item = R;
479    type IntoIter = BroadcastIterator<'b,BMap<'a,R,T,F,DIM>,DIM>;
480    fn into_iter(self) -> Self::IntoIter  {
481        self.bc_iter()
482    }
483}
484
485impl<'a,R, T : Broadcastable<DIM>, F :  Fn(T::Element) -> R  , const DIM: usize>  BMap<'a,R,T,F,DIM> {
486    pub fn iter(&self) ->   BroadcastIterator<BMap<'a,R,T,F,DIM>,DIM>  {
487        self.bc_iter()
488    }
489}
490
491
492
493/// Creates a lazy Broadcastable from an arbitrary function or closure.
494pub fn broadcast_closure<T,F : Fn([usize;N]) -> T,const N : usize>(closure : F,size : [usize;N]) -> BroadcastClosure<T,F,N> {
495    BroadcastClosure {closure,size}
496}
497
498/// Return type of broadcast_closure.
499pub struct BroadcastClosure<T,F : Fn([usize;N]) -> T,const N : usize> {
500    size : [usize;N],
501    closure : F
502}
503impl<T,F : Fn([usize;N]) -> T,const N : usize> TensorDimension for BroadcastClosure<T,F,N> {
504    const DIM : usize = N;
505}
506impl<T,F : Fn([usize;N]) -> T,const N : usize> TensorSize<N> for BroadcastClosure<T,F,N> {
507    fn size(&self) -> [usize;N] {
508        self.size
509    }
510}
511impl<T,F : Fn([usize;N]) -> T,const N : usize> Broadcastable<N> for BroadcastClosure<T,F,N> {
512    type Element = T;
513    fn bget(&self,index : [usize;N]) -> Option<T> {
514        let closure = &self.closure;
515        Some(closure(index))
516    }
517}
518
519
520impl<'a,T,F : Fn([usize;N]) -> T,const N : usize> IntoIterator for &'a BroadcastClosure<T,F,N> {
521    type Item = T;
522    type IntoIter = BroadcastIterator<'a, BroadcastClosure<T,F,N>,N>;
523    fn into_iter(self) -> Self::IntoIter  {
524        self.bc_iter()
525    }
526}
527
528impl<T,F : Fn([usize;N]) -> T,const N : usize> BroadcastClosure<T,F,N> {
529    pub fn iter(&self) -> BroadcastIterator<BroadcastClosure<T,F,N>,N>  {
530        self.bc_iter()
531    }
532}
533
534
535
536
537
538
539
540impl <'a,T> TensorDimension for &'a[T] {
541    const DIM : usize = 1;
542}
543impl <'a,T> TensorSize<1> for &'a [T] {
544    fn size(&self) -> [usize;1] {[self.len()]}
545}
546impl<'a,T> Broadcastable<1> for &'a [T] {
547    type Element = &'a T;
548    fn bget(&self,[index] : [usize;1]) -> Option<&'a T> {
549        self.get(index)
550    }
551}
552
553impl <'a,T> TensorDimension for &'a mut [T] {
554    const DIM : usize = 1;
555}
556impl <'a,T> TensorSize<1> for &'a mut [T] {
557    fn size(&self) -> [usize;1] {[self.len()]}
558}
559impl<'a,T> BroadcastReceiver<1> for &'a mut [T] {
560    type Element = T;
561    fn bget_mut(&mut self,[index] : [usize;1]) -> Option<&mut T> {
562        self.get_mut(index)
563    }
564}
565
566
567
568impl <'a,T,const N : usize> TensorDimension for &'a [T;N] {
569    const DIM : usize = 1;
570}
571impl <'a,T,const N : usize> TensorSize<1> for &'a [T;N] {
572    fn size(&self) -> [usize;1] {[self.len()]}
573}
574impl<'a,T,const N : usize> Broadcastable<1> for &'a [T;N] {
575    type Element = &'a T;
576    fn bget(&self,[index] : [usize;1]) -> Option<&'a T> {
577        self.get(index)
578    }
579}
580
581
582
583impl <T,const N : usize> TensorDimension for [T;N] {
584    const DIM : usize = 1;
585}
586impl <T,const N : usize> TensorSize<1> for [T;N] {
587    fn size(&self) -> [usize;1] {[N]}
588}
589impl<T : Copy,const N : usize> Broadcastable<1> for[T;N] {
590    type Element = T;
591    fn bget(&self,[index] : [usize;1]) -> Option<T> {
592        self.get(index).cloned()
593    }
594}
595impl<T,const N : usize> BroadcastReceiver<1> for [T;N] {
596    type Element = T;
597    fn bget_mut(&mut self,[index] : [usize;1]) -> Option<&mut T> {
598        self.get_mut(index)
599    }
600}
601
602
603#[cfg(feature = "std")] 
604impl<T> TensorDimension for Vec<T> {
605    const DIM : usize = 1;
606}
607#[cfg(feature = "std")] 
608impl<T> TensorSize<1> for Vec<T> {
609    fn size(&self) -> [usize;1] {[self.len()]}
610}
611#[cfg(feature = "std")] 
612impl<'a,T> TensorDimension for &'a Vec<T> {
613    const DIM : usize = 1;
614}
615#[cfg(feature = "std")] 
616impl<'a, T> TensorSize<1> for &'a Vec<T> {
617    fn size(&self) -> [usize;1] {[self.len()]}
618}
619#[cfg(feature = "std")] 
620impl<'a,T> TensorDimension for &'a mut Vec<T> {
621    const DIM : usize = 1;
622}
623#[cfg(feature = "std")]
624impl<'a, T> TensorSize<1> for &'a mut Vec<T> {
625    fn size(&self) -> [usize;1] {[self.len()]}
626}
627#[cfg(feature = "std")]
628impl<'a,T> Broadcastable<1> for &'a Vec<T> {
629    type Element = &'a T;
630    fn bget(&self,index : [usize;1]) -> Option<&'a T> {
631        self.get(index[0])
632    }
633}
634#[cfg(feature = "std")]
635impl<T: Copy> Broadcastable<1> for Vec<T> {
636    type Element = T;
637    fn bget(&self,index : [usize;1]) -> Option<T> {
638        self.get(index[0]).cloned()
639    }
640}
641#[cfg(feature = "std")]
642impl<'a,T> BroadcastReceiver<1> for &'a mut Vec<T> {
643    type Element = T;
644    fn bget_mut(&mut self,[index] : [usize;1]) -> Option<&mut T> {
645        self.get_mut(index)
646    }
647}