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! {
54    DefaultLike::default_like,
55    OnesLike::ones_like,
56    ZerosLike::zeros_like,
57    FillLike::<T>::fill_like(elem: T)
58}
59
60/*
61 ************* Implementations *************
62*/
63impl<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);