|
1 | | -//! Linear Operator |
| 1 | +//! Linear operator algebra |
2 | 2 |
|
| 3 | +use crate::generate::hstack; |
| 4 | +use crate::types::*; |
3 | 5 | use ndarray::*; |
4 | 6 |
|
5 | | -use super::types::*; |
| 7 | +/// Abstracted linear operator as an action to vector (`ArrayBase<S, Ix1>`) and matrix |
| 8 | +/// (`ArrayBase<S, Ix2`) |
| 9 | +pub trait LinearOperator { |
| 10 | + type Elem: Scalar; |
6 | 11 |
|
7 | | -pub trait Operator<A, S, D> |
8 | | -where |
9 | | - S: Data<Elem = A>, |
10 | | - D: Dimension, |
11 | | -{ |
12 | | - fn op(&self, a: &ArrayBase<S, D>) -> Array<A, D>; |
13 | | -} |
14 | | - |
15 | | -pub trait OperatorInto<S, D> |
16 | | -where |
17 | | - S: DataMut, |
18 | | - D: Dimension, |
19 | | -{ |
20 | | - fn op_into(&self, a: ArrayBase<S, D>) -> ArrayBase<S, D>; |
21 | | -} |
22 | | - |
23 | | -pub trait OperatorInplace<S, D> |
24 | | -where |
25 | | - S: DataMut, |
26 | | - D: Dimension, |
27 | | -{ |
28 | | - fn op_inplace<'a>(&self, a: &'a mut ArrayBase<S, D>) -> &'a mut ArrayBase<S, D>; |
29 | | -} |
| 12 | + /// Apply operator out-place |
| 13 | + fn apply<S>(&self, a: &ArrayBase<S, Ix1>) -> Array1<S::Elem> |
| 14 | + where |
| 15 | + S: Data<Elem = Self::Elem>, |
| 16 | + { |
| 17 | + let mut a = a.to_owned(); |
| 18 | + self.apply_mut(&mut a); |
| 19 | + a |
| 20 | + } |
30 | 21 |
|
31 | | -impl<T, A, S, D> Operator<A, S, D> for T |
32 | | -where |
33 | | - A: Scalar + Lapack, |
34 | | - S: Data<Elem = A>, |
35 | | - D: Dimension, |
36 | | - T: linalg::Dot<ArrayBase<S, D>, Output = Array<A, D>>, |
37 | | -{ |
38 | | - fn op(&self, rhs: &ArrayBase<S, D>) -> Array<A, D> { |
39 | | - self.dot(rhs) |
| 22 | + /// Apply operator in-place |
| 23 | + fn apply_mut<S>(&self, a: &mut ArrayBase<S, Ix1>) |
| 24 | + where |
| 25 | + S: DataMut<Elem = Self::Elem>, |
| 26 | + { |
| 27 | + let b = self.apply(a); |
| 28 | + azip!(mut a(a), b in { *a = b }); |
40 | 29 | } |
41 | | -} |
42 | 30 |
|
43 | | -pub trait OperatorMulti<A, S, D> |
44 | | -where |
45 | | - S: Data<Elem = A>, |
46 | | - D: Dimension, |
47 | | -{ |
48 | | - fn op_multi(&self, a: &ArrayBase<S, D>) -> Array<A, D>; |
49 | | -} |
| 31 | + /// Apply operator with move |
| 32 | + fn apply_into<S>(&self, mut a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix1> |
| 33 | + where |
| 34 | + S: DataOwned<Elem = Self::Elem> + DataMut, |
| 35 | + { |
| 36 | + self.apply_mut(&mut a); |
| 37 | + a |
| 38 | + } |
50 | 39 |
|
51 | | -impl<T, A, S, D> OperatorMulti<A, S, D> for T |
52 | | -where |
53 | | - A: Scalar + Lapack, |
54 | | - S: DataMut<Elem = A>, |
55 | | - D: Dimension + RemoveAxis, |
56 | | - for<'a> T: OperatorInplace<ViewRepr<&'a mut A>, D::Smaller>, |
57 | | -{ |
58 | | - fn op_multi(&self, a: &ArrayBase<S, D>) -> Array<A, D> { |
59 | | - let a = a.to_owned(); |
60 | | - self.op_multi_into(a) |
| 40 | + /// Apply operator to matrix out-place |
| 41 | + fn apply2<S>(&self, a: &ArrayBase<S, Ix2>) -> Array2<S::Elem> |
| 42 | + where |
| 43 | + S: Data<Elem = Self::Elem>, |
| 44 | + { |
| 45 | + let cols: Vec<_> = a.axis_iter(Axis(1)).map(|col| self.apply(&col)).collect(); |
| 46 | + hstack(&cols).unwrap() |
61 | 47 | } |
62 | | -} |
63 | 48 |
|
64 | | -pub trait OperatorMultiInto<S, D> |
65 | | -where |
66 | | - S: DataMut, |
67 | | - D: Dimension, |
68 | | -{ |
69 | | - fn op_multi_into(&self, a: ArrayBase<S, D>) -> ArrayBase<S, D>; |
70 | | -} |
| 49 | + /// Apply operator to matrix in-place |
| 50 | + fn apply2_mut<S>(&self, a: &mut ArrayBase<S, Ix2>) |
| 51 | + where |
| 52 | + S: DataMut<Elem = Self::Elem>, |
| 53 | + { |
| 54 | + for mut col in a.axis_iter_mut(Axis(1)) { |
| 55 | + self.apply_mut(&mut col) |
| 56 | + } |
| 57 | + } |
71 | 58 |
|
72 | | -impl<T, A, S, D> OperatorMultiInto<S, D> for T |
73 | | -where |
74 | | - S: DataMut<Elem = A>, |
75 | | - D: Dimension + RemoveAxis, |
76 | | - for<'a> T: OperatorInplace<ViewRepr<&'a mut A>, D::Smaller>, |
77 | | -{ |
78 | | - fn op_multi_into(&self, mut a: ArrayBase<S, D>) -> ArrayBase<S, D> { |
79 | | - self.op_multi_inplace(&mut a); |
| 59 | + /// Apply operator to matrix with move |
| 60 | + fn apply2_into<S>(&self, mut a: ArrayBase<S, Ix2>) -> ArrayBase<S, Ix2> |
| 61 | + where |
| 62 | + S: DataOwned<Elem = Self::Elem> + DataMut, |
| 63 | + { |
| 64 | + self.apply2_mut(&mut a); |
80 | 65 | a |
81 | 66 | } |
82 | 67 | } |
83 | 68 |
|
84 | | -pub trait OperatorMultiInplace<S, D> |
| 69 | +impl<A, Sa> LinearOperator for ArrayBase<Sa, Ix2> |
85 | 70 | where |
86 | | - S: DataMut, |
87 | | - D: Dimension, |
| 71 | + A: Scalar, |
| 72 | + Sa: Data<Elem = A>, |
88 | 73 | { |
89 | | - fn op_multi_inplace<'a>(&self, a: &'a mut ArrayBase<S, D>) -> &'a mut ArrayBase<S, D>; |
90 | | -} |
| 74 | + type Elem = A; |
91 | 75 |
|
92 | | -impl<T, A, S, D> OperatorMultiInplace<S, D> for T |
93 | | -where |
94 | | - S: DataMut<Elem = A>, |
95 | | - D: Dimension + RemoveAxis, |
96 | | - for<'a> T: OperatorInplace<ViewRepr<&'a mut A>, D::Smaller>, |
97 | | -{ |
98 | | - fn op_multi_inplace<'a>(&self, a: &'a mut ArrayBase<S, D>) -> &'a mut ArrayBase<S, D> { |
99 | | - let n = a.ndim(); |
100 | | - for mut col in a.axis_iter_mut(Axis(n - 1)) { |
101 | | - self.op_inplace(&mut col); |
102 | | - } |
103 | | - a |
| 76 | + fn apply<S>(&self, a: &ArrayBase<S, Ix1>) -> Array1<A> |
| 77 | + where |
| 78 | + S: Data<Elem = A>, |
| 79 | + { |
| 80 | + self.dot(a) |
104 | 81 | } |
105 | 82 | } |
0 commit comments