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! {
54 DefaultLike::default_like,
55 OnesLike::ones_like,
56 ZerosLike::zeros_like,
57 FillLike::<T>::fill_like(elem: T)
58}
59
60impl<A, S, D> NdLike<A, D> for ArrayBase<S, D>
64where
65 A: Clone + Num,
66 D: Dimension,
67 S: DataOwned<Elem = A>,
68{
69 type Output = ArrayBase<S, D>;
70
71 fn default_like(&self) -> Self::Output
72 where
73 A: Default,
74 {
75 ArrayBase::default(self.dim())
76 }
77
78 fn ones_like(&self) -> Self::Output
79 where
80 A: One,
81 {
82 ArrayBase::ones(self.dim())
83 }
84
85 fn zeros_like(&self) -> Self::Output
86 where
87 A: Zero,
88 {
89 ArrayBase::zeros(self.dim())
90 }
91}
92
93impl<A, S, D> ArrayLike<A, D> for ArrayBase<S, D>
94where
95 A: Clone,
96 D: Dimension,
97 S: ndarray::DataOwned<Elem = A>,
98{
99 type Output = ArrayBase<S, D>;
100
101 fn array_like<Sh>(&self, shape: Sh, elem: A) -> Self::Output
102 where
103 Sh: ShapeBuilder<Dim = D>,
104 {
105 if self.is_standard_layout() {
106 ArrayBase::from_elem(shape, elem)
107 } else {
108 ArrayBase::from_elem(shape.f(), elem)
109 }
110 }
111}
112
113impl<A, S, D> FillLike<A> for ArrayBase<S, D>
114where
115 A: Clone,
116 D: Dimension,
117 S: DataOwned<Elem = A>,
118{
119 type Output = ArrayBase<S, D>;
120
121 fn fill_like(&self, elem: A) -> Self::Output {
122 ArrayBase::from_elem(self.dim(), elem)
123 }
124}
125
126macro_rules! impl_ndlike {
127
128 ($name:ident::$method:ident.$call:ident: $($p:tt)*) => {
129 impl<A, S, D> $name for ArrayBase<S, D>
130 where
131 A: $($p)*,
132 D: Dimension,
133 S: DataOwned<Elem = A>,
134 {
135 type Output = ArrayBase<S, D>;
136
137 fn $method(&self) -> Self::Output {
138 ArrayBase::$call(self.dim())
139 }
140 }
141 };
142}
143
144impl_ndlike!(DefaultLike::default_like.default: Default);
145impl_ndlike!(OnesLike::ones_like.ones: Clone + One);
146impl_ndlike!(ZerosLike::zeros_like.zeros: Clone + Zero);