concision_core/traits/
like.rs1use 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
55impl<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);