concision_core/traits/
like.rs

1/*
2   Appellation: like <module>
3   Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use ndarray::{ArrayBase, DataOwned, Dimension, Ix2, ShapeBuilder};
6use num::traits::{Num, One, Zero};
7
8pub trait NdLike<A = f64, D = Ix2>
9where
10    A: Clone,
11    D: Dimension,
12{
13    type Output;
14
15    fn default_like(&self) -> Self::Output
16    where
17        A: Default;
18
19    fn ones_like(&self) -> Self::Output
20    where
21        A: One;
22
23    fn zeros_like(&self) -> Self::Output
24    where
25        A: Zero;
26}
27
28pub trait ArrayLike<A = f64, D = Ix2>
29where
30    D: Dimension,
31{
32    type Output;
33
34    fn array_like<Sh>(&self, shape: Sh, elem: A) -> Self::Output
35    where
36        Sh: ShapeBuilder<Dim = D>;
37}
38
39macro_rules! ndlike {
40    ($($name:ident::$(<$($T:ident),*>::)?$method:ident $(($($field:ident:$ft:ty),*))?),* $(,)?) => {
41        $(ndlike!(@impl $name::$(<$($T),*>::)?$method$(($($field:$ft),*))?);)*
42    };
43    (@impl $name:ident::$(<$($T:ident),*>::)?$method:ident$(($($field:ident: $ft:ty),*))?) => {
44        pub trait $name$(<$($T),*>)? {
45            type Output;
46
47            fn $method(&self $(, $($field:$ft),*)?) -> Self::Output;
48        }
49    };
50
51}
52
53ndlike!(DefaultLike::default_like, OnesLike::ones_like, ZerosLike::zeros_like, FillLike::<T>::fill_like(elem: T));
54
55/*
56 ************* Implementations *************
57*/
58impl<A, S, D> NdLike<A, D> for ArrayBase<S, D>
59where
60    A: Clone + Num,
61    D: Dimension,
62    S: DataOwned<Elem = A>,
63{
64    type Output = ArrayBase<S, D>;
65
66    fn default_like(&self) -> Self::Output
67    where
68        A: Default,
69    {
70        ArrayBase::default(self.dim())
71    }
72
73    fn ones_like(&self) -> Self::Output
74    where
75        A: One,
76    {
77        ArrayBase::ones(self.dim())
78    }
79
80    fn zeros_like(&self) -> Self::Output
81    where
82        A: Zero,
83    {
84        ArrayBase::zeros(self.dim())
85    }
86}
87
88impl<A, S, D> ArrayLike<A, D> for ArrayBase<S, D>
89where
90    A: Clone,
91    D: Dimension,
92    S: ndarray::DataOwned<Elem = A>,
93{
94    type Output = ArrayBase<S, D>;
95
96    fn array_like<Sh>(&self, shape: Sh, elem: A) -> Self::Output
97    where
98        Sh: ShapeBuilder<Dim = D>,
99    {
100        if self.is_standard_layout() {
101            ArrayBase::from_elem(shape, elem)
102        } else {
103            ArrayBase::from_elem(shape.f(), elem)
104        }
105    }
106}
107
108impl<A, S, D> FillLike<A> for ArrayBase<S, D>
109where
110    A: Clone,
111    D: Dimension,
112    S: DataOwned<Elem = A>,
113{
114    type Output = ArrayBase<S, D>;
115
116    fn fill_like(&self, elem: A) -> Self::Output {
117        ArrayBase::from_elem(self.dim(), elem)
118    }
119}
120
121macro_rules! impl_ndlike {
122
123    ($name:ident::$method:ident.$call:ident: $($p:tt)*) => {
124        impl<A, S, D> $name for ArrayBase<S, D>
125        where
126            A: $($p)*,
127            D: Dimension,
128            S: DataOwned<Elem = A>,
129        {
130            type Output = ArrayBase<S, D>;
131
132            fn $method(&self) -> Self::Output {
133                ArrayBase::$call(self.dim())
134            }
135        }
136    };
137}
138
139impl_ndlike!(DefaultLike::default_like.default: Default);
140impl_ndlike!(OnesLike::ones_like.ones: Clone + One);
141impl_ndlike!(ZerosLike::zeros_like.zeros: Clone + Zero);