1 //=================================================================================================
2 /*!
3 //  \file blaze/math/expressions/MatScalarMultExpr.h
4 //  \brief Header file for the MatScalarMultExpr 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_MATSCALARMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_MATSCALARMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
44 #include <blaze/math/Exception.h>
45 #include <blaze/math/expressions/Forward.h>
46 #include <blaze/math/expressions/MultExpr.h>
47 #include <blaze/math/typetraits/IsInvertible.h>
48 #include <blaze/math/typetraits/IsScalar.h>
49 #include <blaze/util/Assert.h>
50 #include <blaze/util/EnableIf.h>
51 #include <blaze/util/FunctionTrace.h>
52 
53 
54 namespace blaze {
55 
56 //=================================================================================================
57 //
58 //  CLASS DEFINITION
59 //
60 //=================================================================================================
61 
62 //*************************************************************************************************
63 /*!\brief Base class for all matrix/scalar multiplication expression templates.
64 // \ingroup math
65 //
66 // The MatScalarMultExpr class serves as a tag for all expression templates that implement a
67 // matrix/scalar multiplication. All classes, that represent a matrix/scalar multiplication
68 // and that are used within the expression template environment of the Blaze library have
69 // to derive publicly from this class in order to qualify as matrix/scalar multiplication
70 // expression template. Only in case a class is derived publicly from the MatScalarMultExpr
71 // base class, the IsMatScalarMultExpr type trait recognizes the class as valid matrix/scalar
72 // multiplication expression template.
73 */
74 template< typename MT >  // Matrix base type of the expression
75 struct MatScalarMultExpr
76    : public MultExpr<MT>
77 {};
78 //*************************************************************************************************
79 
80 
81 
82 
83 //=================================================================================================
84 //
85 //  GLOBAL RESTRUCTURING UNARY ARITHMETIC OPERATORS
86 //
87 //=================================================================================================
88 
89 //*************************************************************************************************
90 /*! \cond BLAZE_INTERNAL */
91 /*!\brief Unary minus operator for the negation of a matrix-scalar multiplication
92 //        (\f$ A = -(B*s) \f$).
93 // \ingroup math
94 //
95 // \param mat The matrix-scalar multiplication to be negated.
96 // \return The negation of the matrix-scalar multiplication.
97 //
98 // This operator implements a performance optimized treatment of the negation of a matrix-scalar
99 // multiplication expression.
100 */
101 template< typename MT >  // Matrix base type of the expression
102 inline decltype(auto) operator-( const MatScalarMultExpr<MT>& mat )
103 {
104    BLAZE_FUNCTION_TRACE;
105 
106    return (*mat).leftOperand() * ( -(*mat).rightOperand() );
107 }
108 /*! \endcond */
109 //*************************************************************************************************
110 
111 
112 
113 
114 //=================================================================================================
115 //
116 //  GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
117 //
118 //=================================================================================================
119 
120 //*************************************************************************************************
121 /*! \cond BLAZE_INTERNAL */
122 /*!\brief Multiplication operator for the multiplication of a matrix-scalar multiplication
123 //        expression and a scalar value (\f$ A=(B*s1)*s2 \f$).
124 // \ingroup math
125 //
126 // \param mat The left-hand side matrix-scalar multiplication.
127 // \param scalar The right-hand side scalar value for the multiplication.
128 // \return The scaled result matrix.
129 //
130 // This operator implements a performance optimized treatment of the multiplication of a
131 // matrix-scalar multiplication expression and a scalar value.
132 */
133 template< typename MT  // Matrix base type of the expression
134         , typename ST  // Type of the right-hand side scalar
135         , EnableIf_t< IsScalar_v<ST> >* = nullptr >
decltype(auto)136 inline decltype(auto) operator*( const MatScalarMultExpr<MT>& mat, ST scalar )
137 {
138    BLAZE_FUNCTION_TRACE;
139 
140    return (*mat).leftOperand() * ( (*mat).rightOperand() * scalar );
141 }
142 /*! \endcond */
143 //*************************************************************************************************
144 
145 
146 //*************************************************************************************************
147 /*! \cond BLAZE_INTERNAL */
148 /*!\brief Multiplication operator for the multiplication of a scalar value and a matrix-scalar
149 //        multiplication expression (\f$ A=s2*(B*s1) \f$).
150 // \ingroup math
151 //
152 // \param scalar The left-hand side scalar value for the multiplication.
153 // \param mat The right-hand side matrix-scalar multiplication.
154 // \return The scaled result matrix.
155 //
156 // This operator implements a performance optimized treatment of the multiplication of a
157 // scalar value and a matrix-scalar multiplication expression.
158 */
159 template< typename ST  // Type of the left-hand side scalar
160         , typename MT  // Matrix base type of the expression
161         , EnableIf_t< IsScalar_v<ST> >* = nullptr >
decltype(auto)162 inline decltype(auto) operator*( ST scalar, const MatScalarMultExpr<MT>& mat )
163 {
164    BLAZE_FUNCTION_TRACE;
165 
166    return (*mat).leftOperand() * ( scalar * (*mat).rightOperand() );
167 }
168 /*! \endcond */
169 //*************************************************************************************************
170 
171 
172 //*************************************************************************************************
173 /*! \cond BLAZE_INTERNAL */
174 /*!\brief Division operator for the division of a matrix-scalar multiplication expression by
175 //        a scalar value (\f$ A=(B*s1)/s2 \f$).
176 // \ingroup math
177 //
178 // \param mat The left-hand side matrix-scalar multiplication.
179 // \param scalar The right-hand side scalar value for the division.
180 // \return The scaled result matrix.
181 //
182 // This operator implements a performance optimized treatment of the division of a
183 // matrix-scalar multiplication expression by a scalar value.
184 */
185 template< typename MT  // Matrix base type of the expression
186         , typename ST  // Type of the right-hand side scalar
187         , EnableIf_t< IsScalar_v<ST> &&
188                       ( IsInvertible_v<ST> ||
189                         IsInvertible_v< RightOperand_t< MatrixType_t<MT> > > ) >* = nullptr >
190 inline decltype(auto) operator/( const MatScalarMultExpr<MT>& mat, ST scalar )
191 {
192    BLAZE_FUNCTION_TRACE;
193 
194    BLAZE_USER_ASSERT( scalar != ST(0), "Division by zero detected" );
195 
196    return (*mat).leftOperand() * ( (*mat).rightOperand() / scalar );
197 }
198 /*! \endcond */
199 //*************************************************************************************************
200 
201 
202 //*************************************************************************************************
203 /*! \cond BLAZE_INTERNAL */
204 /*!\brief Multiplication operator for the multiplication of a matrix-scalar multiplication
205 //        expression and a dense vector (\f$ \vec{a}=(B*s1)*\vec{c} \f$).
206 // \ingroup math
207 //
208 // \param mat The left-hand side matrix-scalar multiplication.
209 // \param vec The right-hand side dense vector.
210 // \return The scaled result vector.
211 //
212 // This operator implements the performance optimized treatment of the multiplication
213 // of a matrix-scalar multiplication and a dense vector. It restructures the expression
214 // \f$ \vec{a}=(B*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
215 */
216 template< typename MT    // Matrix base type of the left-hand side expression
217         , typename VT >  // Type of the right-hand side dense vector
decltype(auto)218 inline decltype(auto)
219    operator*( const MatScalarMultExpr<MT>& mat, const DenseVector<VT,false>& vec )
220 {
221    BLAZE_FUNCTION_TRACE;
222 
223    return ( (*mat).leftOperand() * (*vec) ) * (*mat).rightOperand();
224 }
225 /*! \endcond */
226 //*************************************************************************************************
227 
228 
229 //*************************************************************************************************
230 /*! \cond BLAZE_INTERNAL */
231 /*!\brief Multiplication operator for the multiplication of a dense vector and a
232 //        matrix-scalar multiplication expression (\f$ \vec{a}^T=\vec{c}^T*(B*s1) \f$).
233 // \ingroup math
234 //
235 // \param vec The left-hand side dense vector.
236 // \param mat The right-hand side matrix-scalar multiplication.
237 // \return The scaled result vector.
238 //
239 // This operator implements the performance optimized treatment of the multiplication
240 // of a dense vector and a matrix-scalar multiplication. It restructures the expression
241 // \f$ \vec{a}=\vec{c}^T*(B*s1) \f$ to the expression \f$ \vec{a}^T=(\vec{c}^T*B)*s1 \f$.
242 */
243 template< typename VT    // Type of the left-hand side dense vector
244         , typename MT >  // Matrix base type of the right-hand side expression
decltype(auto)245 inline decltype(auto)
246    operator*( const DenseVector<VT,true>& vec, const MatScalarMultExpr<MT>& mat )
247 {
248    BLAZE_FUNCTION_TRACE;
249 
250    return ( (*vec) * (*mat).leftOperand() ) * (*mat).rightOperand();
251 }
252 /*! \endcond */
253 //*************************************************************************************************
254 
255 
256 //*************************************************************************************************
257 /*! \cond BLAZE_INTERNAL */
258 /*!\brief Multiplication operator for the multiplication of a matrix-scalar multiplication
259 //        expression and a sparse vector (\f$ \vec{a}=(B*s1)*\vec{c} \f$).
260 // \ingroup math
261 //
262 // \param mat The left-hand side matrix-scalar multiplication.
263 // \param vec The right-hand side sparse vector.
264 // \return The scaled result vector.
265 //
266 // This operator implements the performance optimized treatment of the multiplication
267 // of a matrix-scalar multiplication and a sparse vector. It restructures the expression
268 // \f$ \vec{a}=(B*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
269 */
270 template< typename MT    // Matrix base type of the left-hand side expression
271         , typename VT >  // Type of the right-hand side sparse vector
decltype(auto)272 inline decltype(auto)
273    operator*( const MatScalarMultExpr<MT>& mat, const SparseVector<VT,false>& vec )
274 {
275    BLAZE_FUNCTION_TRACE;
276 
277    return ( (*mat).leftOperand() * (*vec) ) * (*mat).rightOperand();
278 }
279 /*! \endcond */
280 //*************************************************************************************************
281 
282 
283 //*************************************************************************************************
284 /*! \cond BLAZE_INTERNAL */
285 /*!\brief Multiplication operator for the multiplication of a sparse vector and a
286 //        matrix-scalar multiplication expression (\f$ \vec{a}^T=\vec{c}^T*(B*s1) \f$).
287 // \ingroup math
288 //
289 // \param vec The left-hand side sparse vector.
290 // \param mat The right-hand side matrix-scalar multiplication.
291 // \return The scaled result vector.
292 //
293 // This operator implements the performance optimized treatment of the multiplication
294 // of a sparse vector and a matrix-scalar multiplication. It restructures the expression
295 // \f$ \vec{a}=\vec{c}^T*(B*s1) \f$ to the expression \f$ \vec{a}^T=(\vec{c}^T*B)*s1 \f$.
296 */
297 template< typename VT    // Type of the left-hand side sparse vector
298         , typename MT >  // Matrix base type of the right-hand side expression
decltype(auto)299 inline decltype(auto)
300    operator*( const SparseVector<VT,true>& vec, const MatScalarMultExpr<MT>& mat )
301 {
302    BLAZE_FUNCTION_TRACE;
303 
304    return ( (*vec) * (*mat).leftOperand() ) * (*mat).rightOperand();
305 }
306 /*! \endcond */
307 //*************************************************************************************************
308 
309 
310 //*************************************************************************************************
311 /*! \cond BLAZE_INTERNAL */
312 /*!\brief Multiplication operator for the multiplication of a matrix-scalar multiplication
313 //        expression and a vector-scalar multiplication expression
314 //        (\f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$).
315 // \ingroup math
316 //
317 // \param mat The left-hand side matrix-scalar multiplication.
318 // \param vec The right-hand side vector-scalar multiplication.
319 // \return The scaled result vector.
320 //
321 // This operator implements the performance optimized treatment of the multiplication of a matrix-
322 // scalar multiplication and a vector-scalar multiplication. It restructures the expression
323 // \f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$ to the expression \f$ \vec{a}=(B*\vec{c})*(s1*s2) \f$.
324 */
325 template< typename MT    // Matrix base type of the left-hand side expression
326         , typename VT >  // Vector base type of the right-hand side expression
decltype(auto)327 inline decltype(auto)
328    operator*( const MatScalarMultExpr<MT>& mat, const VecScalarMultExpr<VT>& vec )
329 {
330    BLAZE_FUNCTION_TRACE;
331 
332    return ( (*mat).leftOperand() * (*vec).leftOperand() ) * ( (*mat).rightOperand() * (*vec).rightOperand() );
333 }
334 /*! \endcond */
335 //*************************************************************************************************
336 
337 
338 //*************************************************************************************************
339 /*! \cond BLAZE_INTERNAL */
340 /*!\brief Multiplication operator for the multiplication of a vector-scalar multiplication
341 //        expression and a matrix-scalar multiplication expression
342 //        (\f$ \vec{a}^T=\vec{b}^T*(C*s1) \f$).
343 // \ingroup math
344 //
345 // \param vec The left-hand side vector-scalar multiplication.
346 // \param mat The right-hand side matrix-scalar multiplication.
347 // \return The scaled result vector.
348 //
349 // This operator implements the performance optimized treatment of the multiplication of a vector-
350 // scalar multiplication and a matrix-scalar multiplication. It restructures the expression
351 // \f$ \vec{a}=(\vec{b}^T*s1)*(C*s2) \f$ to the expression \f$ \vec{a}^T=(\vec{b}^T*C)*(s1*s2) \f$.
352 */
353 template< typename VT    // Vector base type of the left-hand side expression
354         , typename MT >  // Matrix base type of the right-hand side expression
decltype(auto)355 inline decltype(auto)
356    operator*( const VecScalarMultExpr<VT>& vec, const MatScalarMultExpr<MT>& mat )
357 {
358    BLAZE_FUNCTION_TRACE;
359 
360    return ( (*vec).leftOperand() * (*mat).leftOperand() ) * ( (*vec).rightOperand() * (*mat).rightOperand() );
361 }
362 /*! \endcond */
363 //*************************************************************************************************
364 
365 
366 //*************************************************************************************************
367 /*! \cond BLAZE_INTERNAL */
368 /*!\brief Multiplication operator for the multiplication of a matrix-scalar multiplication
369 //        expression and a dense matrix (\f$ A=(B*s1)*C \f$).
370 // \ingroup math
371 //
372 // \param lhs The left-hand side matrix-scalar multiplication.
373 // \param rhs The right-hand side dense matrix.
374 // \return The scaled result matrix.
375 //
376 // This operator implements the performance optimized treatment of the multiplication
377 // of a matrix-scalar multiplication and a dense matrix. It restructures the expression
378 // \f$ A=(B*s1)*C \f$ to the expression \f$ A=(B*C)*s1 \f$.
379 */
380 template< typename MT1  // Matrix base type of the left-hand side expression
381         , typename MT2  // Type of the right-hand side dense matrix
382         , bool SO >     // Storage order of the right-hand side dense matrix
decltype(auto)383 inline decltype(auto)
384    operator*( const MatScalarMultExpr<MT1>& lhs, const DenseMatrix<MT2,SO>& rhs )
385 {
386    BLAZE_FUNCTION_TRACE;
387 
388    return ( (*lhs).leftOperand() * (*rhs) ) * (*lhs).rightOperand();
389 }
390 /*! \endcond */
391 //*************************************************************************************************
392 
393 
394 //*************************************************************************************************
395 /*! \cond BLAZE_INTERNAL */
396 /*!\brief Multiplication operator for the multiplication of a dense matrix and a matrix-scalar
397 //        multiplication expression (\f$ A=(B*s1)*C \f$).
398 // \ingroup math
399 //
400 // \param lhs The left-hand side dense matrix.
401 // \param rhs The right-hand side matrix-scalar multiplication.
402 // \return The scaled result matrix.
403 //
404 // This operator implements the performance optimized treatment of the multiplication
405 // of a dense matrix and a matrix-scalar multiplication. It restructures the expression
406 // \f$ A=B*(C*s1) \f$ to the expression \f$ A=(B*C)*s1 \f$.
407 */
408 template< typename MT1    // Type of the left-hand side dense matrix
409         , bool SO         // Storage order of the left-hand side dense matrix
410         , typename MT2 >  // Matrix base type of the right-hand side expression
decltype(auto)411 inline decltype(auto)
412    operator*( const DenseMatrix<MT1,SO>& lhs, const MatScalarMultExpr<MT2>& rhs )
413 {
414    BLAZE_FUNCTION_TRACE;
415 
416    return ( (*lhs) * (*rhs).leftOperand() ) * (*rhs).rightOperand();
417 }
418 /*! \endcond */
419 //*************************************************************************************************
420 
421 
422 //*************************************************************************************************
423 /*! \cond BLAZE_INTERNAL */
424 /*!\brief Multiplication operator for the multiplication of a matrix-scalar multiplication
425 //        expression and a sparse matrix (\f$ A=(B*s1)*C \f$).
426 // \ingroup math
427 //
428 // \param lhs The left-hand side matrix-scalar multiplication.
429 // \param rhs The right-hand side sparse matrix.
430 // \return The scaled result matrix.
431 //
432 // This operator implements the performance optimized treatment of the multiplication
433 // of a matrix-scalar multiplication and a sparse matrix. It restructures the expression
434 // \f$ A=(B*s1)*C \f$ to the expression \f$ A=(B*C)*s1 \f$.
435 */
436 template< typename MT1  // Matrix base type of the left-hand side expression
437         , typename MT2  // Type of the right-hand side sparse matrix
438         , bool SO >     // Storage order of the right-hand side sparse matrix
decltype(auto)439 inline decltype(auto)
440    operator*( const MatScalarMultExpr<MT1>& lhs, const SparseMatrix<MT2,SO>& rhs )
441 {
442    BLAZE_FUNCTION_TRACE;
443 
444    return ( (*lhs).leftOperand() * (*rhs) ) * (*lhs).rightOperand();
445 }
446 /*! \endcond */
447 //*************************************************************************************************
448 
449 
450 //*************************************************************************************************
451 /*! \cond BLAZE_INTERNAL */
452 /*!\brief Multiplication operator for the multiplication of a sparse matrix and a matrix-scalar
453 //        multiplication expression (\f$ A=(B*s1)*C \f$).
454 // \ingroup math
455 //
456 // \param lhs The left-hand side sparse  matrix.
457 // \param rhs The right-hand side matrix-scalar multiplication.
458 // \return The scaled result matrix.
459 //
460 // This operator implements the performance optimized treatment of the multiplication
461 // of a sparse matrix and a matrix-scalar multiplication. It restructures the expression
462 // \f$ A=B*(C*s1) \f$ to the expression \f$ A=(B*C)*s1 \f$.
463 */
464 template< typename MT1    // Type of the left-hand side sparse matrix
465         , bool SO         // Storage order of the left-hand side sparse matrix
466         , typename MT2 >  // Matrix base type of the right-hand side expression
decltype(auto)467 inline decltype(auto)
468    operator*( const SparseMatrix<MT1,SO>& lhs, const MatScalarMultExpr<MT2>& rhs )
469 {
470    BLAZE_FUNCTION_TRACE;
471 
472    return ( (*lhs) * (*rhs).leftOperand() ) * (*rhs).rightOperand();
473 }
474 /*! \endcond */
475 //*************************************************************************************************
476 
477 
478 //*************************************************************************************************
479 /*! \cond BLAZE_INTERNAL */
480 /*!\brief Multiplication operator for the multiplication of two matrix-scalar multiplication
481 //        expressions (\f$ A=(B*s1)*(C*s2) \f$).
482 // \ingroup math
483 //
484 // \param lhs The left-hand side matrix-scalar multiplication.
485 // \param rhs The right-hand side matrix-scalar multiplication.
486 // \return The scaled result matrix.
487 //
488 // This operator implements the performance optimized treatment of the multiplication of
489 // two matrix-scalar multiplication expressions. It restructures the expression
490 // \f$ A=(B*s1)*(C*s2) \f$ to the expression \f$ A=(B*C)*(s1*s2) \f$.
491 */
492 template< typename MT1    // Matrix base type of the left-hand side expression
493         , typename MT2 >  // Matrix base type of the right-hand side expression
decltype(auto)494 inline decltype(auto)
495    operator*( const MatScalarMultExpr<MT1>& lhs, const MatScalarMultExpr<MT2>& rhs )
496 {
497    BLAZE_FUNCTION_TRACE;
498 
499    return ( (*lhs).leftOperand() * (*rhs).leftOperand() ) * ( (*lhs).rightOperand() * (*rhs).rightOperand() );
500 }
501 /*! \endcond */
502 //*************************************************************************************************
503 
504 
505 
506 
507 //=================================================================================================
508 //
509 //  GLOBAL RESTRUCTURING FUNCTIONS
510 //
511 //=================================================================================================
512 
513 //*************************************************************************************************
514 /*! \cond BLAZE_INTERNAL */
515 /*!\brief Calculation of the transpose of the given matrix-scalar multiplication.
516 // \ingroup math
517 //
518 // \param matrix The matrix-scalar multiplication expression to be transposed.
519 // \return The transpose of the expression.
520 //
521 // This operator implements the performance optimized treatment of the transpose of a
522 // matrix-scalar multiplication. It restructures the expression \f$ A=trans(B*s1) \f$ to
523 // the expression \f$ A=trans(B)*s1 \f$.
524 */
525 template< typename MT >  // Matrix base type of the expression
decltype(auto)526 inline decltype(auto) trans( const MatScalarMultExpr<MT>& matrix )
527 {
528    BLAZE_FUNCTION_TRACE;
529 
530    return trans( (*matrix).leftOperand() ) * (*matrix).rightOperand();
531 }
532 /*! \endcond */
533 //*************************************************************************************************
534 
535 
536 //*************************************************************************************************
537 /*! \cond BLAZE_INTERNAL */
538 /*!\brief Calculation of the complex conjugate of the given matrix-scalar multiplication.
539 // \ingroup math
540 //
541 // \param matrix The matrix-scalar multiplication expression to be conjugated.
542 // \return The complex conjugate of the expression.
543 //
544 // This operator implements the performance optimized treatment of the complex conjugate of a
545 // matrix-scalar multiplication. It restructures the expression \f$ a=conj(b*s1) \f$ to the
546 // expression \f$ a=conj(b)*s1 \f$.
547 */
548 template< typename MT >  // Matrix base type of the expression
decltype(auto)549 inline decltype(auto) conj( const MatScalarMultExpr<MT>& matrix )
550 {
551    BLAZE_FUNCTION_TRACE;
552 
553    return conj( (*matrix).leftOperand() ) * (*matrix).rightOperand();
554 }
555 /*! \endcond */
556 //*************************************************************************************************
557 
558 
559 //*************************************************************************************************
560 /*! \cond BLAZE_INTERNAL */
561 /*!\brief Declares the given non-symmetric matrix-scalar multiplication expression as symmetric.
562 // \ingroup math
563 //
564 // \param matrix The input matrix-scalar multiplication expression.
565 // \return The redeclared expression.
566 // \exception std::invalid_argument Invalid symmetric matrix specification.
567 //
568 // This function implements the application of the \a declsym operation on a matrix-scalar
569 // multiplication. It restructures the expression \f$ A=declsym(B*s1) \f$ to the expression
570 // \f$ A=declsym(B)*s1 \f$. In case the given matrix is not a square matrix, a
571 // \a std::invalid_argument exception is thrown.
572 */
573 template< typename MT >  // Matrix base type of the expression
decltype(auto)574 inline decltype(auto) declsym( const MatScalarMultExpr<MT>& matrix )
575 {
576    BLAZE_FUNCTION_TRACE;
577 
578    if( !isSquare( *matrix ) ) {
579       BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
580    }
581 
582    return declsym( (*matrix).leftOperand() ) * (*matrix).rightOperand();
583 }
584 /*! \endcond */
585 //*************************************************************************************************
586 
587 
588 //*************************************************************************************************
589 /*! \cond BLAZE_INTERNAL */
590 /*!\brief Declares the given non-Hermitian matrix-scalar multiplication expression as Hermitian.
591 // \ingroup math
592 //
593 // \param matrix The input matrix-scalar multiplication expression.
594 // \return The redeclared expression.
595 // \exception std::invalid_argument Invalid Hermitian matrix specification.
596 //
597 // This function implements the application of the declherm() operation on a matrix-scalar
598 // multiplication. It restructures the expression \f$ A=declherm(B*s1) \f$ to the expression
599 // \f$ A=declherm(B)*s1 \f$. In case the given matrix is not a square matrix,
600 // a \a std::invalid_argument exception is thrown.
601 */
602 template< typename MT >  // Matrix base type of the expression
decltype(auto)603 inline decltype(auto) declherm( const MatScalarMultExpr<MT>& matrix )
604 {
605    BLAZE_FUNCTION_TRACE;
606 
607    if( !isSquare( *matrix ) ) {
608       BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
609    }
610 
611    return declherm( (*matrix).leftOperand() ) * (*matrix).rightOperand();
612 }
613 /*! \endcond */
614 //*************************************************************************************************
615 
616 
617 //*************************************************************************************************
618 /*! \cond BLAZE_INTERNAL */
619 /*!\brief Declares the given non-lower matrix-scalar multiplication expression as lower.
620 // \ingroup math
621 //
622 // \param matrix The input matrix-scalar multiplication expression.
623 // \return The redeclared expression.
624 // \exception std::invalid_argument Invalid lower matrix specification.
625 //
626 // This function implements the application of the decllow() operation on a matrix-scalar
627 // multiplication. It restructures the expression \f$ A=decllow(B*s1) \f$ to the expression
628 // \f$ A=decllow(B)*s1 \f$. In case the given matrix is not a square matrix,
629 // a \a std::invalid_argument exception is thrown.
630 */
631 template< typename MT >  // Matrix base type of the expression
decltype(auto)632 inline decltype(auto) decllow( const MatScalarMultExpr<MT>& matrix )
633 {
634    BLAZE_FUNCTION_TRACE;
635 
636    if( !isSquare( *matrix ) ) {
637       BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
638    }
639 
640    return decllow( (*matrix).leftOperand() ) * (*matrix).rightOperand();
641 }
642 /*! \endcond */
643 //*************************************************************************************************
644 
645 
646 //*************************************************************************************************
647 /*! \cond BLAZE_INTERNAL */
648 /*!\brief Declares the given non-unilower matrix-scalar multiplication expression as unilower.
649 // \ingroup math
650 //
651 // \param matrix The input matrix-scalar multiplication expression.
652 // \return The redeclared expression.
653 // \exception std::invalid_argument Invalid unilower matrix specification.
654 //
655 // This function implements the application of the declunilow() operation on a matrix-scalar
656 // multiplication. It restructures the expression \f$ A=declunilow(B*s1) \f$ to the expression
657 // \f$ A=declunilow(B)*s1 \f$. In case the given matrix is not a square matrix,
658 // a \a std::invalid_argument exception is thrown.
659 */
660 template< typename MT >  // Matrix base type of the expression
decltype(auto)661 inline decltype(auto) declunilow( const MatScalarMultExpr<MT>& matrix )
662 {
663    BLAZE_FUNCTION_TRACE;
664 
665    if( !isSquare( *matrix ) ) {
666       BLAZE_THROW_INVALID_ARGUMENT( "Invalid unilower matrix specification" );
667    }
668 
669    return declunilow( (*matrix).leftOperand() ) * (*matrix).rightOperand();
670 }
671 /*! \endcond */
672 //*************************************************************************************************
673 
674 
675 //*************************************************************************************************
676 /*! \cond BLAZE_INTERNAL */
677 /*!\brief Declares the given non-strictly-lower matrix-scalar multiplication expression as
678 //        strictly lower.
679 // \ingroup math
680 //
681 // \param matrix The input matrix-scalar multiplication expression.
682 // \return The redeclared expression.
683 // \exception std::invalid_argument Invalid strictly lower matrix specification.
684 //
685 // This function implements the application of the declstrlow() operation on a matrix-scalar
686 // multiplication. It restructures the expression \f$ A=declstrlow(B*s1) \f$ to the expression
687 // \f$ A=declstrlow(B)*s1 \f$. In case the given matrix is not a square matrix,
688 // a \a std::invalid_argument exception is thrown.
689 */
690 template< typename MT >  // Matrix base type of the expression
decltype(auto)691 inline decltype(auto) declstrlow( const MatScalarMultExpr<MT>& matrix )
692 {
693    BLAZE_FUNCTION_TRACE;
694 
695    if( !isSquare( *matrix ) ) {
696       BLAZE_THROW_INVALID_ARGUMENT( "Invalid strictly lower matrix specification" );
697    }
698 
699    return declstrlow( (*matrix).leftOperand() ) * (*matrix).rightOperand();
700 }
701 /*! \endcond */
702 //*************************************************************************************************
703 
704 
705 //*************************************************************************************************
706 /*! \cond BLAZE_INTERNAL */
707 /*!\brief Declares the given non-upper matrix-scalar multiplication expression as upper.
708 // \ingroup math
709 //
710 // \param matrix The input matrix-scalar multiplication expression.
711 // \return The redeclared expression.
712 // \exception std::invalid_argument Invalid upper matrix specification.
713 //
714 // This function implements the application of the declupp() operation on a matrix-scalar
715 // multiplication. It restructures the expression \f$ A=declupp(B*s1) \f$ to the expression
716 // \f$ A=declupp(B)*s1 \f$. In case the given matrix is not a square matrix,
717 // a \a std::invalid_argument exception is thrown.
718 */
719 template< typename MT >  // Matrix base type of the expression
decltype(auto)720 inline decltype(auto) declupp( const MatScalarMultExpr<MT>& matrix )
721 {
722    BLAZE_FUNCTION_TRACE;
723 
724    if( !isSquare( *matrix ) ) {
725       BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
726    }
727 
728    return declupp( (*matrix).leftOperand() ) * (*matrix).rightOperand();
729 }
730 /*! \endcond */
731 //*************************************************************************************************
732 
733 
734 //*************************************************************************************************
735 /*! \cond BLAZE_INTERNAL */
736 /*!\brief Declares the given non-uniupper matrix-scalar multiplication expression as uniupper.
737 // \ingroup math
738 //
739 // \param matrix The input matrix-scalar multiplication expression.
740 // \return The redeclared expression.
741 // \exception std::invalid_argument Invalid uniupper matrix specification.
742 //
743 // This function implements the application of the decluniupp() operation on a matrix-scalar
744 // multiplication. It restructures the expression \f$ A=decluniupp(B*s1) \f$ to the expression
745 // \f$ A=decluniupp(B)*s1 \f$. In case the given matrix is not a square matrix,
746 // a \a std::invalid_argument exception is thrown.
747 */
748 template< typename MT >  // Matrix base type of the expression
decltype(auto)749 inline decltype(auto) decluniupp( const MatScalarMultExpr<MT>& matrix )
750 {
751    BLAZE_FUNCTION_TRACE;
752 
753    if( !isSquare( *matrix ) ) {
754       BLAZE_THROW_INVALID_ARGUMENT( "Invalid uniupper matrix specification" );
755    }
756 
757    return decluniupp( (*matrix).leftOperand() ) * (*matrix).rightOperand();
758 }
759 /*! \endcond */
760 //*************************************************************************************************
761 
762 
763 //*************************************************************************************************
764 /*! \cond BLAZE_INTERNAL */
765 /*!\brief Declares the given non-strictly-upper matrix-scalar multiplication expression as
766 //        strictly upper.
767 // \ingroup math
768 //
769 // \param matrix The input matrix-scalar multiplication expression.
770 // \return The redeclared expression.
771 // \exception std::invalid_argument Invalid strictly upper matrix specification.
772 //
773 // This function implements the application of the declstrupp() operation on a matrix-scalar
774 // multiplication. It restructures the expression \f$ A=declstrupp(B*s1) \f$ to the expression
775 // \f$ A=declstrupp(B)*s1 \f$. In case the given matrix is not a square matrix,
776 // a \a std::invalid_argument exception is thrown.
777 */
778 template< typename MT >  // Matrix base type of the expression
decltype(auto)779 inline decltype(auto) declstrupp( const MatScalarMultExpr<MT>& matrix )
780 {
781    BLAZE_FUNCTION_TRACE;
782 
783    if( !isSquare( *matrix ) ) {
784       BLAZE_THROW_INVALID_ARGUMENT( "Invalid strictly upper matrix specification" );
785    }
786 
787    return declstrupp( (*matrix).leftOperand() ) * (*matrix).rightOperand();
788 }
789 /*! \endcond */
790 //*************************************************************************************************
791 
792 
793 //*************************************************************************************************
794 /*! \cond BLAZE_INTERNAL */
795 /*!\brief Declares the given non-diagonal matrix-scalar multiplication expression as diagonal.
796 // \ingroup math
797 //
798 // \param matrix The input matrix-scalar multiplication expression.
799 // \return The redeclared expression.
800 // \exception std::invalid_argument Invalid diagonal matrix specification.
801 //
802 // This function implements the application of the decldiag() operation on a matrix-scalar
803 // multiplication. It restructures the expression \f$ A=decldiag(B*s1) \f$ to the expression
804 // \f$ A=decldiag(B)*s1 \f$. In case the given matrix is not a square matrix,
805 // a \a std::invalid_argument exception is thrown.
806 */
807 template< typename MT >  // Matrix base type of the expression
decltype(auto)808 inline decltype(auto) decldiag( const MatScalarMultExpr<MT>& matrix )
809 {
810    BLAZE_FUNCTION_TRACE;
811 
812    if( !isSquare( *matrix ) ) {
813       BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
814    }
815 
816    return decldiag( (*matrix).leftOperand() ) * (*matrix).rightOperand();
817 }
818 /*! \endcond */
819 //*************************************************************************************************
820 
821 } // namespace blaze
822 
823 #endif
824