1use crate::{
4 LinearOp, LinearOpSens, LinearOpTranspose, Matrix, NonLinearOp, NonLinearOpAdjoint,
5 NonLinearOpJacobian, NonLinearOpSens, NonLinearOpSensAdjoint, Op, Vector,
6};
7use num_traits::{One, Zero};
8
9use super::{BuilderOp, ParameterisedOp};
10
11pub struct UnitCallable<M: Matrix> {
13 n: usize,
14 ctx: M::C,
15}
16
17impl<M: Matrix> Default for UnitCallable<M> {
18 fn default() -> Self {
19 Self::new(1, M::C::default())
20 }
21}
22
23impl<M: Matrix> UnitCallable<M> {
24 pub fn new(n: usize, ctx: M::C) -> Self {
25 Self { n, ctx }
26 }
27}
28
29impl<M: Matrix> Op for UnitCallable<M> {
30 type T = M::T;
31 type V = M::V;
32 type M = M;
33 type C = M::C;
34 fn nstates(&self) -> usize {
35 self.n
36 }
37 fn nout(&self) -> usize {
38 self.n
39 }
40 fn nparams(&self) -> usize {
41 0
42 }
43 fn context(&self) -> &Self::C {
44 &self.ctx
45 }
46}
47
48impl<M: Matrix> BuilderOp for UnitCallable<M> {
49 fn calculate_sparsity(&mut self, _y0: &Self::V, _t0: Self::T, _p: &Self::V) {
50 }
52 fn set_nout(&mut self, nout: usize) {
53 self.n = nout;
54 }
55 fn set_nparams(&mut self, _nparams: usize) {
56 }
58 fn set_nstates(&mut self, nstates: usize) {
59 self.n = nstates;
60 }
61}
62
63impl<M: Matrix> LinearOp for ParameterisedOp<'_, UnitCallable<M>> {
64 fn gemv_inplace(&self, x: &Self::V, _t: Self::T, beta: Self::T, y: &mut Self::V) {
65 y.axpy(Self::T::one(), x, beta);
66 }
67}
68
69impl<M: Matrix> NonLinearOp for ParameterisedOp<'_, UnitCallable<M>> {
70 fn call_inplace(&self, x: &Self::V, _t: Self::T, y: &mut Self::V) {
71 y.copy_from(x);
72 }
73}
74
75impl<M: Matrix> NonLinearOpJacobian for ParameterisedOp<'_, UnitCallable<M>> {
76 fn jac_mul_inplace(&self, _x: &Self::V, _t: Self::T, v: &Self::V, y: &mut Self::V) {
77 y.copy_from(v);
78 }
79}
80
81impl<M: Matrix> NonLinearOpAdjoint for ParameterisedOp<'_, UnitCallable<M>> {
82 fn jac_transpose_mul_inplace(&self, _x: &Self::V, _t: Self::T, v: &Self::V, y: &mut Self::V) {
83 y.copy_from(v);
84 }
85}
86
87impl<M: Matrix> NonLinearOpSens for ParameterisedOp<'_, UnitCallable<M>> {
88 fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
89 y.fill(Self::T::zero());
90 }
91}
92
93impl<M: Matrix> NonLinearOpSensAdjoint for ParameterisedOp<'_, UnitCallable<M>> {
94 fn sens_transpose_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
95 y.fill(Self::T::zero());
96 }
97}
98
99impl<M: Matrix> LinearOpSens for ParameterisedOp<'_, UnitCallable<M>> {
100 fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
101 y.fill(Self::T::zero());
102 }
103}
104
105impl<M: Matrix> LinearOpTranspose for ParameterisedOp<'_, UnitCallable<M>> {
106 fn gemv_transpose_inplace(&self, x: &Self::V, _t: Self::T, beta: Self::T, y: &mut Self::V) {
107 y.axpy(Self::T::one(), x, beta);
108 }
109}
110
111impl<M: Matrix> LinearOp for UnitCallable<M> {
112 fn gemv_inplace(&self, x: &Self::V, _t: Self::T, beta: Self::T, y: &mut Self::V) {
113 y.axpy(Self::T::one(), x, beta);
114 }
115}
116
117impl<M: Matrix> NonLinearOp for UnitCallable<M> {
118 fn call_inplace(&self, x: &Self::V, _t: Self::T, y: &mut Self::V) {
119 y.copy_from(x);
120 }
121}
122
123impl<M: Matrix> NonLinearOpJacobian for UnitCallable<M> {
124 fn jac_mul_inplace(&self, _x: &Self::V, _t: Self::T, v: &Self::V, y: &mut Self::V) {
125 y.copy_from(v);
126 }
127}
128
129impl<M: Matrix> NonLinearOpAdjoint for UnitCallable<M> {
130 fn jac_transpose_mul_inplace(&self, _x: &Self::V, _t: Self::T, v: &Self::V, y: &mut Self::V) {
131 y.copy_from(v);
132 }
133}
134
135impl<M: Matrix> NonLinearOpSens for UnitCallable<M> {
136 fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
137 y.fill(Self::T::zero());
138 }
139}
140
141impl<M: Matrix> NonLinearOpSensAdjoint for UnitCallable<M> {
142 fn sens_transpose_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
143 y.fill(Self::T::zero());
144 }
145}
146
147impl<M: Matrix> LinearOpSens for UnitCallable<M> {
148 fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
149 y.fill(Self::T::zero());
150 }
151}
152
153impl<M: Matrix> LinearOpTranspose for UnitCallable<M> {
154 fn gemv_transpose_inplace(&self, x: &Self::V, _t: Self::T, beta: Self::T, y: &mut Self::V) {
155 y.axpy(Self::T::one(), x, beta);
156 }
157}