codac 2.0.0
Loading...
Searching...
No Matches
codac2_det.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include "codac2_Interval.h"
15#include "codac2_AnalyticType.h"
17#include "codac2_arith_sub.h"
18#include "codac2_arith_mul.h"
19
20namespace codac2
21{
22 struct DetOp
23 {
24 template<typename X1>
25 static std::string str(const X1& x1)
26 {
27 return "det(" + x1->str() + ")";
28 }
29
30 template<typename X1,typename X2>
31 static std::string str(const X1& x1, const X2& x2)
32 {
33 return "det(" + x1->str() + "," + x2->str() + ")";
34 }
35
36 template<typename X1,typename X2,typename X3>
37 static std::string str(const X1& x1, const X2& x2, const X3& x3)
38 {
39 return "det(" + x1->str() + "," + x2->str() + "," + x3->str() + ")";
40 }
41
42 // For matrices
43 template<typename X1>
44 static std::pair<Index,Index> output_shape([[maybe_unused]] const X1& s1) {
45 return {1,1};
46 }
47 static Interval fwd(const IntervalMatrix& x);
48 static ScalarType fwd_natural(const MatrixType& x);
49 static ScalarType fwd_centered(const MatrixType& x);
50 static void bwd(const Interval& y, IntervalMatrix& x);
51
52 // For two vectors (merged into a 2×2 matrix)
53 template<typename X1, typename X2>
54 static std::pair<Index,Index> output_shape([[maybe_unused]] const X1& s1, [[maybe_unused]] const X2& s2) {
55 return {1,1};
56 }
57 static Interval fwd(const IntervalVector& x1, const IntervalVector& x2);
58 static ScalarType fwd_natural(const VectorType& x1, const VectorType& x2);
59 static ScalarType fwd_centered(const VectorType& x1, const VectorType& x2);
60 static void bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2);
61
62 // For three vectors (merged into a 3×3 matrix)
63 template<typename X1, typename X2, typename X3>
64 static std::pair<Index,Index> output_shape([[maybe_unused]] const X1& s1, [[maybe_unused]] const X2& s2, [[maybe_unused]] const X3& s3) {
65 return {1,1};
66 }
67 static Interval fwd(const IntervalVector& x1, const IntervalVector& x2, const IntervalVector& x3);
68 static ScalarType fwd_natural(const VectorType& x1, const VectorType& x2, const VectorType& x3);
69 static ScalarType fwd_centered(const VectorType& x1, const VectorType& x2, const VectorType& x3);
70 static void bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2, IntervalVector& x3);
71 };
72
73 // Analytic operator
74 // The following functions can be used to build analytic expressions.
75
76 inline ScalarExpr
77 det(const MatrixExpr& x1)
78 {
79 return { std::make_shared<AnalyticOperationExpr<DetOp,ScalarType,MatrixType>>(x1) };
80 }
81
82 inline ScalarExpr
83 det(const VectorExpr& x1, const VectorExpr& x2)
84 {
85 return { std::make_shared<AnalyticOperationExpr<DetOp,ScalarType,VectorType,VectorType>>(x1,x2) };
86 }
87
88 inline ScalarExpr
89 det(const VectorExpr& x1, const VectorExpr& x2, const VectorExpr& x3)
90 {
91 return { std::make_shared<AnalyticOperationExpr<DetOp,ScalarType,VectorType,VectorType,VectorType>>(x1,x2,x3) };
92 }
93
94 // Inline functions
95
96 inline Interval DetOp::fwd(const IntervalMatrix& x)
97 {
98 assert_release(x.is_squared() && "can only compute determinants for a square matrix");
99 assert_release((x.rows() == 1 || x.rows() == 2) && "determinant not yet computable for n×n matrices, n>2");
100
101 if(x.rows() == 1) // 1×1 matrix
102 return x(0,0);
103
104 else if(x.rows() == 2) // 2×2 matrix
105 return x(0,0)*x(1,1)-x(0,1)*x(1,0);
106
107 else
108 return Interval::empty(); // unhandled case
109 }
110
111 inline ScalarType DetOp::fwd_natural(const MatrixType& x)
112 {
113 return {
114 fwd(x.a),
115 x.def_domain
116 };
117 }
118
119 inline ScalarType DetOp::fwd_centered(const MatrixType& x)
120 {
121 if(centered_form_not_available_for_args(x))
122 return fwd_natural(x);
123
124 if(x.a.rows()==1) {
125 return {
126 fwd(x.m),
127 fwd(x.a),
128 x.da, // keep matrix type for diff
129 x.def_domain
130 };
131 }
132
133 IntervalMatrix d(1, x.da.cols());
134 if (x.a.rows()==2) { /* otherwise, will fail afterwards */
135 for (Index i=0; i < d.cols() ; i++) {
136 d(0,i) = x.da(0,i)*x.a(1,1) + x.da(3,i)*x.a(0,0)
137 - x.da(1,i)*x.a(0,1) - x.da(2,i)*x.a(1,0);
138 /* note: ColMajor is assumed here */
139 }
140 }
141
142 return {
143 fwd(x.m),
144 fwd(x.a),
145 d,
146 x.def_domain
147 };
148 }
149
150 inline void DetOp::bwd(const Interval& y, IntervalMatrix& x)
151 {
152 assert_release(x.is_squared() && "can only compute determinants for a square matrix");
153 assert_release((x.rows() == 1 || x.rows() == 2) && "determinant not yet computable for n×n matrices, n>2");
154
155 if(x.rows() == 1) // 1×1 matrix
156 x(0,0) &= y;
157
158 else if(x.rows() == 2) // 2×2 matrix
159 {
160 Interval z1 = x(0,0)*x(1,1), z2 = x(1,0)*x(0,1);
161 SubOp::bwd(y, z1, z2);
162 MulOp::bwd(z1, x(0,0), x(1,1));
163 MulOp::bwd(z2, x(1,0), x(0,1));
164 }
165
166 else
167 {
168 // unhandled case
169 }
170 }
171
172 inline Interval DetOp::fwd(const IntervalVector& x1, const IntervalVector& x2)
173 {
174 assert_release(x1.size() == 2 && x2.size() == 2 && "determinant only computable for pairs of 2d vectors");
175 IntervalMatrix m(2,2);
176 m.col(0) = x1; m.col(1) = x2;
177 return DetOp::fwd(m);
178 }
179
180 inline ScalarType DetOp::fwd_natural(const VectorType& x1, const VectorType& x2)
181 {
182 IntervalMatrix a(2,2);
183 a.col(0) = x1.a; a.col(1) = x2.a;
184
185 return {
186 fwd(a),
187 x1.def_domain && x2.def_domain
188 };
189 }
190
191 inline ScalarType DetOp::fwd_centered(const VectorType& x1, const VectorType& x2)
192 {
193 if(centered_form_not_available_for_args(x1,x2))
194 return fwd_natural(x1,x2);
195
196 IntervalMatrix m(2,2);
197 m.col(0) = x1.m; m.col(1) = x2.m;
198 IntervalMatrix a(2,2);
199 a.col(0) = x1.a; a.col(1) = x2.a;
200
201 assert(x1.da.cols() == x2.da.cols());
202 IntervalMatrix d(1, x1.da.cols());
203 for (Index i=0; i < d.cols() ; i++) {
204 d(0,i) = x1.da(0,i)*x2.a[1] + x1.a[0]*x2.da(1,i)
205 - x1.da(1,i)*x2.a[0] - x1.a[1]*x2.da(0,i);
206 }
207
208 return {
209 fwd(m),
210 fwd(a),
211 d,
212 x1.def_domain && x2.def_domain
213 };
214 }
215
216 inline void DetOp::bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2)
217 {
218 assert_release(x1.size() == 2 && x2.size() == 2 && "determinant only computable for pairs of 2d vectors");
219 IntervalMatrix m(2,2);
220 m.col(0) = x1; m.col(1) = x2;
221 DetOp::bwd(y,m);
222 x1 &= m.col(0);
223 x2 &= m.col(1);
224 }
225
226 inline Interval DetOp::fwd(const IntervalVector& x1, const IntervalVector& x2, const IntervalVector& x3)
227 {
228 assert_release(x1.size() == 3 && x2.size() == 3 && x3.size() == 3 && "determinant only computable for triplet of 3d vectors");
229 IntervalMatrix m(3,3);
230 m.col(0) = x1; m.col(1) = x2; m.col(2) = x3;
231 return DetOp::fwd(m);
232 }
233
234 inline ScalarType DetOp::fwd_natural(const VectorType& x1, const VectorType& x2, const VectorType& x3)
235 {
236 IntervalMatrix a(3,3);
237 a.col(0) = x1.a; a.col(1) = x2.a; a.col(2) = x3.a;
238
239 return {
240 fwd(a),
241 x1.def_domain && x2.def_domain && x3.def_domain
242 };
243 }
244
245 inline ScalarType DetOp::fwd_centered(const VectorType& x1, const VectorType& x2, const VectorType& x3)
246 {
247 if(centered_form_not_available_for_args(x1,x2,x3))
248 return fwd_natural(x1,x2,x3);
249
250 IntervalMatrix m(3,3);
251 m.col(0) = x1.m; m.col(1) = x2.m; m.col(2) = x3.m;
252 IntervalMatrix a(3,3);
253 a.col(0) = x1.a; a.col(1) = x2.a; a.col(2) = x3.a;
254
255 return {
256 fwd(m),
257 fwd(a),
258 IntervalMatrix(0,0), // not supported yet for auto diff
259 x1.def_domain && x2.def_domain && x3.def_domain
260 };
261 }
262
263 inline void DetOp::bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2, IntervalVector& x3)
264 {
265 assert_release(x1.size() == 3 && x2.size() == 3 && x3.size() == 3 && "determinant only computable for triplet of 3d vectors");
266
267 IntervalMatrix m(3,3);
268 m.col(0) = x1; m.col(1) = x2; m.col(2) = x3;
269
270 DetOp::bwd(y,m);
271 x1 &= m.col(0);
272 x2 &= m.col(1);
273 x3 &= m.col(2);
274 }
275}
Interval class, for representing closed and connected subsets of .
Definition codac2_Interval.h:62
static Interval empty()
Provides an empty interval.
Definition codac2_Interval_impl.h:535