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