concision_core/traits/arr/
ops.rs

1/*
2    Appellation: ops <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use nd::linalg::Dot;
6use nd::*;
7use num::traits::{Num, NumAssign};
8
9pub trait Affine<X, Y = X> {
10    type Output;
11
12    fn affine(&self, mul: X, add: Y) -> Self::Output;
13}
14
15pub trait Inverse {
16    type Output;
17
18    fn inverse(&self) -> Self::Output;
19}
20
21pub trait Matmul<Rhs = Self> {
22    type Output;
23
24    fn matmul(&self, rhs: &Rhs) -> Self::Output;
25}
26
27pub trait Matpow<Rhs = Self> {
28    type Output;
29
30    fn pow(&self, rhs: Rhs) -> Self::Output;
31}
32
33/*
34 ********* Implementations *********
35*/
36impl<A, D> Affine<A> for Array<A, D>
37where
38    A: LinalgScalar + ScalarOperand,
39    D: Dimension,
40{
41    type Output = Array<A, D>;
42
43    fn affine(&self, mul: A, add: A) -> Self::Output {
44        self * mul + add
45    }
46}
47
48// #[cfg(feature = "blas")]
49impl<T> Inverse for Array<T, Ix2>
50where
51    T: Copy + NumAssign + ScalarOperand,
52{
53    type Output = Option<Self>;
54    fn inverse(&self) -> Self::Output {
55        crate::inverse(self)
56    }
57}
58
59impl<S, X, Y> Matmul<X> for S
60where
61    S: Dot<X, Output = Y>,
62{
63    type Output = Y;
64
65    fn matmul(&self, rhs: &X) -> Self::Output {
66        self.dot(rhs)
67    }
68}
69
70impl<A, S> Matpow<i32> for ArrayBase<S, nd::Ix2>
71where
72    A: Copy + Num + 'static,
73    S: Data<Elem = A>,
74    ArrayBase<S, Ix2>: Clone + Dot<ArrayBase<S, Ix2>, Output = Array<A, Ix2>>,
75{
76    type Output = Array<A, Ix2>;
77
78    fn pow(&self, rhs: i32) -> Self::Output {
79        if !self.is_square() {
80            panic!("Matrix must be square to be raised to a power");
81        }
82        let mut res = Array::eye(self.shape()[0]);
83        for _ in 0..rhs {
84            res = res.dot(self);
85        }
86        res
87    }
88}