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