1 //=================================================================================================
2 /*!
3 // \file blaze/math/expressions/MatInvExpr.h
4 // \brief Header file for the MatInvExpr base class
5 //
6 // Copyright (C) 2012-2020 Klaus Iglberger - All Rights Reserved
7 //
8 // This file is part of the Blaze library. You can redistribute it and/or modify it under
9 // the terms of the New (Revised) BSD License. Redistribution and use in source and binary
10 // forms, with or without modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright notice, this list of
14 // conditions and the following disclaimer.
15 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
16 // of conditions and the following disclaimer in the documentation and/or other materials
17 // provided with the distribution.
18 // 3. Neither the names of the Blaze development group nor the names of its contributors
19 // may be used to endorse or promote products derived from this software without specific
20 // prior written permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 // SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 */
33 //=================================================================================================
34
35 #ifndef _BLAZE_MATH_EXPRESSIONS_MATINVEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_MATINVEXPR_H_
37
38
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42
43 #include <blaze/math/expressions/Expression.h>
44 #include <blaze/math/expressions/Forward.h>
45 #include <blaze/math/shims/Invert.h>
46 #include <blaze/math/typetraits/IsMatScalarMultExpr.h>
47 #include <blaze/util/FunctionTrace.h>
48
49
50 namespace blaze {
51
52 //=================================================================================================
53 //
54 // CLASS DEFINITION
55 //
56 //=================================================================================================
57
58 //*************************************************************************************************
59 /*!\brief Base class for all matrix inversion expression templates.
60 // \ingroup math
61 //
62 // The MatInvExpr class serves as a tag for all expression templates that implement a matrix
63 // inversion operation. All classes, that represent a matrix inversion operation and that are
64 // used within the expression template environment of the Blaze library have to derive publicly
65 // from this class in order to qualify as matrix inversion expression template. Only in case
66 // a class is derived publicly from the MatInvExpr base class, the IsMatInvExpr type trait
67 // recognizes the class as valid matrix inversion expression template.
68 */
69 template< typename MT > // Matrix base type of the expression
70 struct MatInvExpr
71 : public Expression<MT>
72 {};
73 //*************************************************************************************************
74
75
76
77
78 //=================================================================================================
79 //
80 // GLOBAL RESTRUCTURING FUNCTIONS
81 //
82 //=================================================================================================
83
84 //*************************************************************************************************
85 /*! \cond BLAZE_INTERNAL */
86 /*!\brief Multiplication operator for the multiplication of a matrix inversion expression
87 // and a dense vector (\f$ \vec{y}=inv(A)*\vec{x} \f$).
88 // \ingroup math
89 //
90 // \param mat The left-hand side matrix inversion.
91 // \param vec The right-hand side dense vector for the multiplication.
92 // \return The resulting vector.
93 //
94 // This operator implements a performance optimized treatment of the multiplication of a
95 // matrix inversion expression and a dense vector. It restructures the expression
96 // \f$ \vec{x}=inv(A)*\vec{x} \f$ to the expression \f$ \vec{y}=solve(A,\vec{x}) \f$.
97 */
98 template< typename MT // Matrix base type of the left-hand side expression
99 , typename VT > // Type of the right-hand side dense vector
decltype(auto)100 inline decltype(auto)
101 operator*( const MatInvExpr<MT>& mat, const DenseVector<VT,false>& vec )
102 {
103 BLAZE_FUNCTION_TRACE;
104
105 return solve( (*mat).operand(), *vec );
106 }
107 /*! \endcond */
108 //*************************************************************************************************
109
110
111 //*************************************************************************************************
112 /*! \cond BLAZE_INTERNAL */
113 /*!\brief Multiplication operator for the multiplication of a transpose dense vector and a
114 // matrix inversion expression (\f$ \vec{y}=\vec{x}*inv(A) \f$).
115 // \ingroup math
116 //
117 // \param vec The left-hand side transpose dense vector for the multiplication.
118 // \param mat The right-hand side matrix inversion for the multiplication.
119 // \return The resulting vector.
120 //
121 // This operator implements a performance optimized treatment of the multiplication of a
122 // transpose dense vector and a matrix inversion expression. It restructures the expression
123 // \f$ \vec{x}=\vec{x}*inv(A) \f$ to the expression \f$ \vec{y}=solve(A^T,\vec{x}) \f$.
124 */
125 template< typename VT // Type of the left-hand side dense vector
126 , typename MT > // Matrix base type of the right-hand side expression
decltype(auto)127 inline decltype(auto)
128 operator*( const DenseVector<VT,true>& vec, const MatInvExpr<MT>& mat )
129 {
130 BLAZE_FUNCTION_TRACE;
131
132 return solve( trans( (*mat).operand() ), *vec );
133 }
134 /*! \endcond */
135 //*************************************************************************************************
136
137
138 //*************************************************************************************************
139 /*! \cond BLAZE_INTERNAL */
140 /*!\brief Multiplication operator for the multiplication of a matrix inversion expression
141 // and a dense matrix (\f$ C=inv(A)*B \f$).
142 // \ingroup math
143 //
144 // \param lhs The left-hand side matrix inversion.
145 // \param rhs The right-hand side dense matrix for the multiplication.
146 // \return The resulting vector.
147 //
148 // This operator implements a performance optimized treatment of the multiplication of a
149 // matrix inversion expression and a dense matrix. It restructures the expression
150 // \f$ C=inv(A)*B \f$ to the expression \f$ C=solve(A,B) \f$.
151 */
152 template< typename MT1 // Matrix base type of the left-hand side expression
153 , typename MT2 // Type of the right-hand side dense matrix
154 , bool SO // Storage order of the right-hand side dense matrix
155 , DisableIf_t< IsMatScalarMultExpr_v<MT2> >* = nullptr >
decltype(auto)156 inline decltype(auto)
157 operator*( const MatInvExpr<MT1>& lhs, const DenseMatrix<MT2,SO>& rhs )
158 {
159 BLAZE_FUNCTION_TRACE;
160
161 return solve( (*lhs).operand(), *rhs );
162 }
163 /*! \endcond */
164 //*************************************************************************************************
165
166
167 //*************************************************************************************************
168 /*! \cond BLAZE_INTERNAL */
169 /*!\brief Multiplication operator for the multiplication of a dense matrix and a matrix inversion
170 // expression (\f$ C=B*inv(A) \f$).
171 // \ingroup math
172 //
173 // \param lhs The left-hand side dense matrix for the multiplication.
174 // \param rhs The right-hand side matrix inversion for the multiplication.
175 // \return The resulting vector.
176 //
177 // This operator implements a performance optimized treatment of the multiplication of a
178 // dense matrix and a matrix inversion expression. It restructures the expression
179 // \f$ C=B*inv(A) \f$ to the expression \f$ C=solve(A^T,B^T)^T \f$.
180 */
181 template< typename MT1 // Type of the left-hand side dense matrix
182 , bool SO // Storage order of the left-hand side dense matrix
183 , typename MT2 // Matrix base type of the right-hand side expression
184 , DisableIf_t< IsMatScalarMultExpr_v<MT1> >* = nullptr >
decltype(auto)185 inline decltype(auto)
186 operator*( const DenseMatrix<MT1,SO>& lhs, const MatInvExpr<MT2>& rhs )
187 {
188 BLAZE_FUNCTION_TRACE;
189
190 return trans( solve( trans( (*rhs).operand() ), trans( *lhs ) ) );
191 }
192 /*! \endcond */
193 //*************************************************************************************************
194
195
196 //*************************************************************************************************
197 /*! \cond BLAZE_INTERNAL */
198 /*!\brief Calculating the inverse of a matrix inversion.
199 // \ingroup math
200 //
201 // \param matrix The matrix to be (re-)inverted.
202 // \return The inverse of the inverted matrix.
203 //
204 // This function implements a performance optimized treatment of the inversion operation on a
205 // matrix inversion expression. It returns an expression representing the inverse of a matrix
206 // inversion:
207
208 \code
209 using blaze::rowMajor;
210
211 blaze::DynamicMatrix<double,rowMajor> A, B;
212 // ... Resizing and initialization
213 B = inv( inv( A ) );
214 \endcode
215 */
216 template< typename MT > // Matrix base type of the expression
decltype(auto)217 inline decltype(auto) inv( const MatInvExpr<MT>& matrix )
218 {
219 BLAZE_FUNCTION_TRACE;
220
221 return matrix.operand();
222 }
223 /*! \endcond */
224 //*************************************************************************************************
225
226
227 //*************************************************************************************************
228 /*! \cond BLAZE_INTERNAL */
229 /*!\brief Computation of the determinant of the given matrix inversion.
230 // \ingroup math
231 //
232 // \param matrix The given matrix inversion.
233 // \return The determinant of the given matrix inversion.
234 //
235 // This function computes the determinant of the given matrix inversion.
236 //
237 // \note The computation of the determinant is numerically unreliable since especially for large
238 // matrices the value can overflow during the computation. Please note that this function does
239 // not guarantee that it is possible to compute the determinant with the given matrix!
240 //
241 // \note This function can only be used if a fitting LAPACK library is available and linked to
242 // the executable. Otherwise a linker error will be created.
243 */
244 template< typename MT > // Matrix base type of the expression
decltype(auto)245 inline decltype(auto) det( const MatInvExpr<MT>& matrix )
246 {
247 BLAZE_FUNCTION_TRACE;
248
249 return inv( det( (*matrix).operand() ) );
250 }
251 /*! \endcond */
252 //*************************************************************************************************
253
254 } // namespace blaze
255
256 #endif
257