1 //================================================================================================= 2 /*! 3 // \file blaze/math/expressions/DMatTSMatAddExpr.h 4 // \brief Header file for the dense matrix/transpose sparse matrix addition expression 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_DMATTSMATADDEXPR_H_ 36 #define _BLAZE_MATH_EXPRESSIONS_DMATTSMATADDEXPR_H_ 37 38 39 //************************************************************************************************* 40 // Includes 41 //************************************************************************************************* 42 43 #include <utility> 44 #include <blaze/math/Aliases.h> 45 #include <blaze/math/constraints/ColumnMajorMatrix.h> 46 #include <blaze/math/constraints/DenseMatrix.h> 47 #include <blaze/math/constraints/MatMatAddExpr.h> 48 #include <blaze/math/constraints/RequiresEvaluation.h> 49 #include <blaze/math/constraints/RowMajorMatrix.h> 50 #include <blaze/math/constraints/SparseMatrix.h> 51 #include <blaze/math/constraints/StorageOrder.h> 52 #include <blaze/math/Exception.h> 53 #include <blaze/math/expressions/Computation.h> 54 #include <blaze/math/expressions/DenseMatrix.h> 55 #include <blaze/math/expressions/Forward.h> 56 #include <blaze/math/expressions/MatMatAddExpr.h> 57 #include <blaze/math/shims/Serial.h> 58 #include <blaze/math/traits/AddTrait.h> 59 #include <blaze/math/typetraits/IsExpression.h> 60 #include <blaze/math/typetraits/IsOperation.h> 61 #include <blaze/math/typetraits/IsTemporary.h> 62 #include <blaze/math/typetraits/IsZero.h> 63 #include <blaze/util/Assert.h> 64 #include <blaze/util/EnableIf.h> 65 #include <blaze/util/FunctionTrace.h> 66 #include <blaze/util/IntegralConstant.h> 67 #include <blaze/util/MaybeUnused.h> 68 #include <blaze/util/mpl/If.h> 69 #include <blaze/util/Types.h> 70 #include <blaze/util/typetraits/IsSame.h> 71 72 73 namespace blaze { 74 75 //================================================================================================= 76 // 77 // CLASS DMATTSMATADDEXPR 78 // 79 //================================================================================================= 80 81 //************************************************************************************************* 82 /*!\brief Expression object for dense matrix-sparse matrix additions. 83 // \ingroup dense_matrix_expression 84 // 85 // The DMatTSMatAddExpr class represents the compile time expression for additions between 86 // a row-major dense matrix and a column-major sparse matrix. 87 */ 88 template< typename MT1 // Type of the left-hand side dense matrix 89 , typename MT2 > // Type of the right-hand side sparse matrix 90 class DMatTSMatAddExpr 91 : public MatMatAddExpr< DenseMatrix< DMatTSMatAddExpr<MT1,MT2>, false > > 92 , private Computation 93 { 94 private: 95 //**Type definitions**************************************************************************** 96 using RT1 = ResultType_t<MT1>; //!< Result type of the left-hand side dense matrix expression. 97 using RT2 = ResultType_t<MT2>; //!< Result type of the right-hand side sparse matrix expression. 98 using RN1 = ReturnType_t<MT1>; //!< Return type of the left-hand side dense matrix expression. 99 using RN2 = ReturnType_t<MT2>; //!< Return type of the right-hand side sparse matrix expression. 100 //********************************************************************************************** 101 102 //**Return type evaluation********************************************************************** 103 //! Compilation switch for the selection of the subscript operator return type. 104 /*! The \a returnExpr compile time constant expression is a compilation switch for the 105 selection of the \a ReturnType. If either matrix operand returns a temporary vector 106 or matrix, \a returnExpr will be set to \a false and the subscript operator will 107 return it's result by value. Otherwise \a returnExpr will be set to \a true and 108 the subscript operator may return it's result as an expression. */ 109 static constexpr bool returnExpr = ( !IsTemporary_v<RN1> && !IsTemporary_v<RN2> ); 110 111 //! Expression return type for the subscript operator. 112 using ExprReturnType = decltype( std::declval<RN1>() + std::declval<RN2>() ); 113 //********************************************************************************************** 114 115 //**Parallel evaluation strategy**************************************************************** 116 /*! \cond BLAZE_INTERNAL */ 117 //! Helper variable template for the explicit application of the SFINAE principle. 118 /*! This variable template is a helper for the selection of the parallel evaluation strategy. 119 In case at least one of the two matrix operands is not SMP assignable, the variable is set 120 to 1 and the expression specific evaluation strategy is selected. Otherwise the variable 121 is set to 0 and the default strategy is chosen. */ 122 template< typename MT > 123 static constexpr bool UseSMPAssign_v = ( !MT1::smpAssignable || !MT2::smpAssignable ); 124 /*! \endcond */ 125 //********************************************************************************************** 126 127 public: 128 //**Type definitions**************************************************************************** 129 //! Type of this DMatTSMatAddExpr instance. 130 using This = DMatTSMatAddExpr<MT1,MT2>; 131 132 //! Base type of this DMatTSMatAddExpr instance. 133 using BaseType = MatMatAddExpr< DenseMatrix<This,false> >; 134 135 using ResultType = AddTrait_t<RT1,RT2>; //!< Result type for expression template evaluations. 136 using OppositeType = OppositeType_t<ResultType>; //!< Result type with opposite storage order for expression template evaluations. 137 using TransposeType = TransposeType_t<ResultType>; //!< Transpose type for expression template evaluations. 138 using ElementType = ElementType_t<ResultType>; //!< Resulting element type. 139 140 //! Return type for expression template evaluations. 141 using ReturnType = const If_t< returnExpr, ExprReturnType, ElementType >; 142 143 //! Data type for composite expression templates. 144 using CompositeType = const ResultType; 145 146 //! Composite type of the left-hand side dense matrix expression. 147 using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >; 148 149 //! Composite type of the right-hand side sparse matrix expression. 150 using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >; 151 //********************************************************************************************** 152 153 //**Compilation flags*************************************************************************** 154 //! Compilation switch for the expression template evaluation strategy. 155 static constexpr bool simdEnabled = false; 156 157 //! Compilation switch for the expression template assignment strategy. 158 static constexpr bool smpAssignable = false; 159 //********************************************************************************************** 160 161 //**Constructor********************************************************************************* 162 /*!\brief Constructor for the DMatTSMatAddExpr class. 163 // 164 // \param lhs The left-hand side dense matrix operand of the addition expression. 165 // \param rhs The right-hand side sparse matrix operand of the addition expression. 166 */ DMatTSMatAddExpr(const MT1 & lhs,const MT2 & rhs)167 inline DMatTSMatAddExpr( const MT1& lhs, const MT2& rhs ) noexcept 168 : lhs_( lhs ) // Left-hand side dense matrix of the addition expression 169 , rhs_( rhs ) // Right-hand side sparse matrix of the addition expression 170 { 171 BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" ); 172 BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" ); 173 } 174 //********************************************************************************************** 175 176 //**Access operator***************************************************************************** 177 /*!\brief 2D-access to the matrix elements. 178 // 179 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. 180 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. 181 // \return The resulting value. 182 */ operator()183 inline ReturnType operator()( size_t i, size_t j ) const { 184 BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" ); 185 BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" ); 186 return lhs_(i,j) + rhs_(i,j); 187 } 188 //********************************************************************************************** 189 190 //**At function********************************************************************************* 191 /*!\brief Checked access to the matrix elements. 192 // 193 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. 194 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. 195 // \return The resulting value. 196 // \exception std::out_of_range Invalid matrix access index. 197 */ at(size_t i,size_t j)198 inline ReturnType at( size_t i, size_t j ) const { 199 if( i >= lhs_.rows() ) { 200 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" ); 201 } 202 if( j >= lhs_.columns() ) { 203 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" ); 204 } 205 return (*this)(i,j); 206 } 207 //********************************************************************************************** 208 209 //**Rows function******************************************************************************* 210 /*!\brief Returns the current number of rows of the matrix. 211 // 212 // \return The number of rows of the matrix. 213 */ rows()214 inline size_t rows() const noexcept { 215 return lhs_.rows(); 216 } 217 //********************************************************************************************** 218 219 //**Columns function**************************************************************************** 220 /*!\brief Returns the current number of columns of the matrix. 221 // 222 // \return The number of columns of the matrix. 223 */ columns()224 inline size_t columns() const noexcept { 225 return lhs_.columns(); 226 } 227 //********************************************************************************************** 228 229 //**Left operand access************************************************************************* 230 /*!\brief Returns the left-hand side dense matrix operand. 231 // 232 // \return The left-hand side dense matrix operand. 233 */ leftOperand()234 inline LeftOperand leftOperand() const { 235 return lhs_; 236 } 237 //********************************************************************************************** 238 239 //**Right operand access************************************************************************ 240 /*!\brief Returns the right-hand side transpose sparse matrix operand. 241 // 242 // \return The right-hand side transpose sparse matrix operand. 243 */ rightOperand()244 inline RightOperand rightOperand() const noexcept { 245 return rhs_; 246 } 247 //********************************************************************************************** 248 249 //********************************************************************************************** 250 /*!\brief Returns whether the expression can alias with the given address \a alias. 251 // 252 // \param alias The alias to be checked. 253 // \return \a true in case the expression can alias, \a false otherwise. 254 */ 255 template< typename T > canAlias(const T * alias)256 inline bool canAlias( const T* alias ) const noexcept { 257 return ( IsExpression_v<MT1> && lhs_.canAlias( alias ) ) || 258 ( rhs_.canAlias( alias ) ); 259 } 260 //********************************************************************************************** 261 262 //********************************************************************************************** 263 /*!\brief Returns whether the expression is aliased with the given address \a alias. 264 // 265 // \param alias The alias to be checked. 266 // \return \a true in case an alias effect is detected, \a false otherwise. 267 */ 268 template< typename T > isAliased(const T * alias)269 inline bool isAliased( const T* alias ) const noexcept { 270 return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) ); 271 } 272 //********************************************************************************************** 273 274 private: 275 //**Member variables**************************************************************************** 276 LeftOperand lhs_; //!< Left-hand side dense matrix of the addition expression. 277 RightOperand rhs_; //!< Right-hand side sparse matrix of the addition expression. 278 //********************************************************************************************** 279 280 //**Assignment to dense matrices**************************************************************** 281 /*! \cond BLAZE_INTERNAL */ 282 /*!\brief Assignment of a dense matrix-transpose sparse matrix addition to a dense matrix. 283 // \ingroup dense_matrix 284 // 285 // \param lhs The target left-hand side dense matrix. 286 // \param rhs The right-hand side addition expression to be assigned. 287 // \return void 288 // 289 // This function implements the performance optimized assignment of a dense matrix-transpose 290 // sparse matrix addition expression to a dense matrix. 291 */ 292 template< typename MT // Type of the target dense matrix 293 , bool SO2 > // Storage order of the target dense matrix assign(DenseMatrix<MT,SO2> & lhs,const DMatTSMatAddExpr & rhs)294 friend inline void assign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 295 { 296 BLAZE_FUNCTION_TRACE; 297 298 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 299 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 300 301 if( !IsOperation_v<MT1> && isSame( *lhs, rhs.lhs_ ) ) { 302 addAssign( *lhs, rhs.rhs_ ); 303 } 304 else { 305 assign ( *lhs, rhs.lhs_ ); 306 addAssign( *lhs, rhs.rhs_ ); 307 } 308 } 309 /*! \endcond */ 310 //********************************************************************************************** 311 312 //**Assignment to sparse matrices*************************************************************** 313 /*! \cond BLAZE_INTERNAL */ 314 /*!\brief Assignment of a dense matrix-transpose sparse matrix addition to a sparse matrix. 315 // \ingroup dense_matrix 316 // 317 // \param lhs The target left-hand side sparse matrix. 318 // \param rhs The right-hand side addition expression to be assigned. 319 // \return void 320 // 321 // This function implements the performance optimized assignment of a dense matrix-transpose 322 // sparse matrix addition expression to a sparse matrix. 323 */ 324 template< typename MT // Type of the target sparse matrix 325 , bool SO2 > // Storage order of the target sparse matrix assign(SparseMatrix<MT,SO2> & lhs,const DMatTSMatAddExpr & rhs)326 friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 327 { 328 BLAZE_FUNCTION_TRACE; 329 330 using TmpType = If_t< SO2, OppositeType, ResultType >; 331 332 BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType ); 333 BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType ); 334 BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType ); 335 BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType ); 336 BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType ); 337 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( TmpType ); 338 339 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 340 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 341 342 const TmpType tmp( serial( rhs ) ); 343 assign( *lhs, tmp ); 344 } 345 /*! \endcond */ 346 //********************************************************************************************** 347 348 //**Addition assignment to dense matrices******************************************************* 349 /*! \cond BLAZE_INTERNAL */ 350 /*!\brief Addition assignment of a dense matrix-transpose sparse matrix addition to a dense 351 // matrix. 352 // \ingroup dense_matrix 353 // 354 // \param lhs The target left-hand side dense matrix. 355 // \param rhs The right-hand side addition expression to be added. 356 // \return void 357 // 358 // This function implements the performance optimized addition assignment of a dense matrix- 359 // transpose sparse matrix addition expression to a dense matrix. 360 */ 361 template< typename MT // Type of the target dense matrix 362 , bool SO2 > // Storage order of the target dense matrix addAssign(DenseMatrix<MT,SO2> & lhs,const DMatTSMatAddExpr & rhs)363 friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 364 { 365 BLAZE_FUNCTION_TRACE; 366 367 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 368 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 369 370 addAssign( *lhs, rhs.lhs_ ); 371 addAssign( *lhs, rhs.rhs_ ); 372 } 373 /*! \endcond */ 374 //********************************************************************************************** 375 376 //**Addition assignment to sparse matrices****************************************************** 377 // No special implementation for the addition assignment to sparse matrices. 378 //********************************************************************************************** 379 380 //**Subtraction assignment to dense matrices**************************************************** 381 /*! \cond BLAZE_INTERNAL */ 382 /*!\brief Subtraction assignment of a dense matrix-transpose sparse matrix addition to a dense 383 // matrix. 384 // \ingroup dense_matrix 385 // 386 // \param lhs The target left-hand side dense matrix. 387 // \param rhs The right-hand side addition expression to be subtracted. 388 // \return void 389 // 390 // This function implements the performance optimized subtraction assignment of a dense matrix- 391 // transpose sparse matrix addition expression to a dense matrix. 392 */ 393 template< typename MT // Type of the target dense matrix 394 , bool SO2 > // Storage order of the target dense matrix subAssign(DenseMatrix<MT,SO2> & lhs,const DMatTSMatAddExpr & rhs)395 friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 396 { 397 BLAZE_FUNCTION_TRACE; 398 399 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 400 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 401 402 subAssign( *lhs, rhs.lhs_ ); 403 subAssign( *lhs, rhs.rhs_ ); 404 } 405 /*! \endcond */ 406 //********************************************************************************************** 407 408 //**Subtraction assignment to sparse matrices*************************************************** 409 // No special implementation for the subtraction assignment to sparse matrices. 410 //********************************************************************************************** 411 412 //**Schur product assignment to dense matrices************************************************** 413 /*! \cond BLAZE_INTERNAL */ 414 /*!\brief Schur product assignment of a dense matrix-transpose sparse matrix addition to a 415 // dense matrix. 416 // \ingroup dense_matrix 417 // 418 // \param lhs The target left-hand side dense matrix. 419 // \param rhs The right-hand side addition expression for the Schur product. 420 // \return void 421 // 422 // This function implements the performance optimized Schur product assignment of a dense 423 // matrix-transpose sparse matrix addition expression to a dense matrix. 424 */ 425 template< typename MT // Type of the target dense matrix 426 , bool SO2 > // Storage order of the target dense matrix schurAssign(DenseMatrix<MT,SO2> & lhs,const DMatTSMatAddExpr & rhs)427 friend inline void schurAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 428 { 429 BLAZE_FUNCTION_TRACE; 430 431 BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType ); 432 BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType ); 433 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); 434 435 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 436 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 437 438 const ResultType tmp( serial( rhs ) ); 439 schurAssign( *lhs, tmp ); 440 } 441 /*! \endcond */ 442 //********************************************************************************************** 443 444 //**Schur product assignment to sparse matrices************************************************* 445 // No special implementation for the Schur product assignment to sparse matrices. 446 //********************************************************************************************** 447 448 //**Multiplication assignment to dense matrices************************************************* 449 // No special implementation for the multiplication assignment to dense matrices. 450 //********************************************************************************************** 451 452 //**Multiplication assignment to sparse matrices************************************************ 453 // No special implementation for the multiplication assignment to sparse matrices. 454 //********************************************************************************************** 455 456 //**SMP assignment to dense matrices************************************************************ 457 /*! \cond BLAZE_INTERNAL */ 458 /*!\brief SMP assignment of a dense matrix-transpose sparse matrix addition to a dense matrix. 459 // \ingroup dense_matrix 460 // 461 // \param lhs The target left-hand side dense matrix. 462 // \param rhs The right-hand side addition expression to be assigned. 463 // \return void 464 // 465 // This function implements the performance optimized SMP assignment of a dense matrix-transpose 466 // sparse matrix addition expression to a dense matrix. Due to the explicit application of the 467 // SFINAE principle, this function can only be selected by the compiler in case the expression 468 // specific parallel evaluation strategy is selected. 469 */ 470 template< typename MT // Type of the target dense matrix 471 , bool SO2 > // Storage order of the target dense matrix 472 friend inline auto smpAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 473 -> EnableIf_t< UseSMPAssign_v<MT> > 474 { 475 BLAZE_FUNCTION_TRACE; 476 477 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 478 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 479 480 if( !IsOperation_v<MT1> && isSame( *lhs, rhs.lhs_ ) ) { 481 smpAddAssign( *lhs, rhs.rhs_ ); 482 } 483 else { 484 smpAssign ( *lhs, rhs.lhs_ ); 485 smpAddAssign( *lhs, rhs.rhs_ ); 486 } 487 } 488 /*! \endcond */ 489 //********************************************************************************************** 490 491 //**SMP assignment to sparse matrices*********************************************************** 492 /*! \cond BLAZE_INTERNAL */ 493 /*!\brief SMP assignment of a dense matrix-transpose sparse matrix addition to a sparse matrix. 494 // \ingroup dense_matrix 495 // 496 // \param lhs The target left-hand side sparse matrix. 497 // \param rhs The right-hand side addition expression to be assigned. 498 // \return void 499 // 500 // This function implements the performance optimized SMP assignment of a dense matrix-transpose 501 // sparse matrix addition expression to a sparse matrix. Due to the explicit application of the 502 // SFINAE principle, this function can only be selected by the compiler in case the expression 503 // specific parallel evaluation strategy is selected. 504 */ 505 template< typename MT // Type of the target sparse matrix 506 , bool SO2 > // Storage order of the target sparse matrix 507 friend inline auto smpAssign( SparseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 508 -> EnableIf_t< UseSMPAssign_v<MT> > 509 { 510 BLAZE_FUNCTION_TRACE; 511 512 using TmpType = If_t< SO2, OppositeType, ResultType >; 513 514 BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType ); 515 BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType ); 516 BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType ); 517 BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType ); 518 BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType ); 519 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( TmpType ); 520 521 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 522 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 523 524 const TmpType tmp( rhs ); 525 smpAssign( *lhs, tmp ); 526 } 527 /*! \endcond */ 528 //********************************************************************************************** 529 530 //**SMP addition assignment to dense matrices*************************************************** 531 /*! \cond BLAZE_INTERNAL */ 532 /*!\brief SMP addition assignment of a dense matrix-transpose sparse matrix addition to a dense 533 // matrix. 534 // \ingroup dense_matrix 535 // 536 // \param lhs The target left-hand side dense matrix. 537 // \param rhs The right-hand side addition expression to be added. 538 // \return void 539 // 540 // This function implements the performance optimized addition assignment of a dense matrix- 541 // transpose sparse matrix addition expression to a dense matrix. Due to the explicit application 542 // of the SFINAE principle, this function can only be selected by the compiler in case the 543 // expression specific parallel evaluation strategy is selected. 544 */ 545 template< typename MT // Type of the target dense matrix 546 , bool SO2 > // Storage order of the target dense matrix 547 friend inline auto smpAddAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 548 -> EnableIf_t< UseSMPAssign_v<MT> > 549 { 550 BLAZE_FUNCTION_TRACE; 551 552 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 553 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 554 555 smpAddAssign( *lhs, rhs.lhs_ ); 556 smpAddAssign( *lhs, rhs.rhs_ ); 557 } 558 /*! \endcond */ 559 //********************************************************************************************** 560 561 //**SMP addition assignment to sparse matrices************************************************** 562 // No special implementation for the SMP addition assignment to sparse matrices. 563 //********************************************************************************************** 564 565 //**SMP subtraction assignment to dense matrices************************************************ 566 /*! \cond BLAZE_INTERNAL */ 567 /*!\brief SMP subtraction assignment of a dense matrix-transpose sparse matrix addition to a dense 568 // matrix. 569 // \ingroup dense_matrix 570 // 571 // \param lhs The target left-hand side dense matrix. 572 // \param rhs The right-hand side addition expression to be subtracted. 573 // \return void 574 // 575 // This function implements the performance optimized SMP subtraction assignment of a dense 576 // matrix-transpose sparse matrix addition expression to a dense matrix. Due to the explicit 577 // application of the SFINAE principle, this function can only be selected by the compiler in 578 // case the expression specific parallel evaluation strategy is selected. 579 */ 580 template< typename MT // Type of the target dense matrix 581 , bool SO2 > // Storage order of the target dense matrix 582 friend inline auto smpSubAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 583 -> EnableIf_t< UseSMPAssign_v<MT> > 584 { 585 BLAZE_FUNCTION_TRACE; 586 587 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 588 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 589 590 smpSubAssign( *lhs, rhs.lhs_ ); 591 smpSubAssign( *lhs, rhs.rhs_ ); 592 } 593 /*! \endcond */ 594 //********************************************************************************************** 595 596 //**SMP subtraction assignment to sparse matrices*********************************************** 597 // No special implementation for the SMP subtraction assignment to sparse matrices. 598 //********************************************************************************************** 599 600 //**SMP Schur product assignment to dense matrices********************************************** 601 /*! \cond BLAZE_INTERNAL */ 602 /*!\brief SMP Schur product assignment of a dense matrix-transpose sparse matrix addition to 603 // a dense matrix. 604 // \ingroup dense_matrix 605 // 606 // \param lhs The target left-hand side dense matrix. 607 // \param rhs The right-hand side addition expression for the Schur product. 608 // \return void 609 // 610 // This function implements the performance optimized SMP Schur product assignment of a dense 611 // matrix-transpose sparse matrix addition expression to a dense matrix. Due to the explicit 612 // application of the SFINAE principle, this function can only be selected by the compiler in 613 // case the expression specific parallel evaluation strategy is selected. 614 */ 615 template< typename MT // Type of the target dense matrix 616 , bool SO2 > // Storage order of the target dense matrix 617 friend inline auto smpSchurAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs ) 618 -> EnableIf_t< UseSMPAssign_v<MT> > 619 { 620 BLAZE_FUNCTION_TRACE; 621 622 BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType ); 623 BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType ); 624 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); 625 626 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" ); 627 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" ); 628 629 const ResultType tmp( rhs ); 630 smpSchurAssign( *lhs, tmp ); 631 } 632 /*! \endcond */ 633 //********************************************************************************************** 634 635 //**SMP Schur product assignment to sparse matrices********************************************* 636 // No special implementation for the SMP Schur product assignment to sparse matrices. 637 //********************************************************************************************** 638 639 //**SMP multiplication assignment to dense matrices********************************************* 640 // No special implementation for the SMP multiplication assignment to dense matrices. 641 //********************************************************************************************** 642 643 //**SMP multiplication assignment to sparse matrices******************************************** 644 // No special implementation for the SMP multiplication assignment to sparse matrices. 645 //********************************************************************************************** 646 647 //**Compile time checks************************************************************************* 648 /*! \cond BLAZE_INTERNAL */ 649 BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 ); 650 BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 ); 651 BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 ); 652 BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 ); 653 BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR( MT1, MT2 ); 654 /*! \endcond */ 655 //********************************************************************************************** 656 }; 657 //************************************************************************************************* 658 659 660 661 662 //================================================================================================= 663 // 664 // GLOBAL BINARY ARITHMETIC OPERATORS 665 // 666 //================================================================================================= 667 668 //************************************************************************************************* 669 /*! \cond BLAZE_INTERNAL */ 670 /*!\brief Backend implementation of the addition between a row-major dense matrix and a 671 // column-major sparse matrix (\f$ A=B+C \f$). 672 // \ingroup dense_matrix 673 // 674 // \param lhs The left-hand side dense matrix for the addition. 675 // \param rhs The right-hand side sparse matrix for the addition. 676 // \return The sum of the two matrices. 677 // 678 // This function implements a performance optimized treatment of the addition between a row-major 679 // dense matrix and a column-major sparse matrix. 680 */ 681 template< typename MT1 // Type of the left-hand side dense matrix 682 , typename MT2 // Type of the right-hand side sparse matrix 683 , DisableIf_t< IsZero_v<MT2> && 684 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr > 685 inline const DMatTSMatAddExpr<MT1,MT2> dmattsmatadd(const DenseMatrix<MT1,false> & lhs,const SparseMatrix<MT2,true> & rhs)686 dmattsmatadd( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,true>& rhs ) 687 { 688 BLAZE_FUNCTION_TRACE; 689 690 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" ); 691 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" ); 692 693 return DMatTSMatAddExpr<MT1,MT2>( *lhs, *rhs ); 694 } 695 /*! \endcond */ 696 //************************************************************************************************* 697 698 699 //************************************************************************************************* 700 /*! \cond BLAZE_INTERNAL */ 701 /*!\brief Backend implementation of the addition between a row-major dense matrix and a 702 // column-major zero matrix (\f$ A=B+C \f$). 703 // \ingroup dense_matrix 704 // 705 // \param lhs The left-hand side dense matrix for the addition. 706 // \param rhs The right-hand side zero matrix for the addition. 707 // \return Reference to the left-hand side dense matrix. 708 // 709 // This function implements a performance optimized treatment of the addition between a row-major 710 // dense matrix and a column-major zero matrix. It returns a reference to the left-hand side dense 711 // matrix. 712 */ 713 template< typename MT1 // Type of the left-hand side dense matrix 714 , typename MT2 // Type of the right-hand side sparse matrix 715 , EnableIf_t< IsZero_v<MT2> && 716 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr > 717 inline const MT1& dmattsmatadd(const DenseMatrix<MT1,false> & lhs,const SparseMatrix<MT2,true> & rhs)718 dmattsmatadd( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,true>& rhs ) 719 { 720 BLAZE_FUNCTION_TRACE; 721 722 MAYBE_UNUSED( rhs ); 723 724 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" ); 725 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" ); 726 727 return (*lhs); 728 } 729 /*! \endcond */ 730 //************************************************************************************************* 731 732 733 //************************************************************************************************* 734 /*!\brief Addition operator for the addition of a row-major dense matrix and a column-major 735 // sparse matrix (\f$ A=B+C \f$). 736 // \ingroup dense_matrix 737 // 738 // \param lhs The left-hand side dense matrix for the matrix addition. 739 // \param rhs The right-hand side sparse matrix to be added to the left-hand side matrix. 740 // \return The sum of the two matrices. 741 // \exception std::invalid_argument Matrix sizes do not match. 742 // 743 // This operator represents the addition of a row-major dense matrix and a column-major sparse 744 // matrix: 745 746 \code 747 using blaze::rowMajor; 748 using blaze::columnMajor; 749 750 blaze::DynamicMatrix<double,rowMajor> A, C; 751 blaze::CompressedMatrix<double,columnMajor> B; 752 // ... Resizing and initialization 753 C = A + B; 754 \endcode 755 756 // The operator returns an expression representing a dense matrix of the higher-order element 757 // type of the two involved matrix element types \a MT1::ElementType and \a MT2::ElementType. 758 // Both matrix types \a MT1 and \a MT2 as well as the two element types \a MT1::ElementType 759 // and \a MT2::ElementType have to be supported by the AddTrait class template.\n 760 // In case the current sizes of the two given matrices don't match, a \a std::invalid_argument 761 // is thrown. 762 */ 763 template< typename MT1 // Type of the left-hand side dense matrix 764 , typename MT2 > // Type of the right-hand side sparse matrix 765 inline decltype(auto) 766 operator+( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,true>& rhs ) 767 { 768 BLAZE_FUNCTION_TRACE; 769 770 if( (*lhs).rows() != (*rhs).rows() || (*lhs).columns() != (*rhs).columns() ) { 771 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); 772 } 773 774 return dmattsmatadd( *lhs, *rhs ); 775 } 776 //************************************************************************************************* 777 778 779 //************************************************************************************************* 780 /*!\brief Addition operator for the addition of a column-major sparse matrix and a row-major 781 // dense matrix (\f$ A=B+C \f$). 782 // \ingroup dense_matrix 783 // 784 // \param lhs The left-hand side sparse matrix for the matrix addition. 785 // \param rhs The right-hand side dense matrix to be added to the left-hand side matrix. 786 // \return The sum of the two matrices. 787 // \exception std::invalid_argument Matrix sizes do not match. 788 // 789 // This operator represents the addition of a column-major sparse matrix and a row-major dense 790 // matrix: 791 792 \code 793 using blaze::rowMajor; 794 using blaze::columnMajor; 795 796 blaze::CompressedMatrix<double,columnMajor> A; 797 blaze::DynamicMatrix<double,rowMajor> B, C; 798 // ... Resizing and initialization 799 C = A + B; 800 \endcode 801 802 // The operator returns an expression representing a dense matrix of the higher-order element 803 // type of the two involved matrix element types \a MT1::ElementType and \a MT2::ElementType. 804 // Both matrix types \a MT1 and \a MT2 as well as the two element types \a MT1::ElementType 805 // and \a MT2::ElementType have to be supported by the AddTrait class template.\n 806 // In case the current sizes of the two given matrices don't match, a \a std::invalid_argument 807 // is thrown. 808 */ 809 template< typename MT1 // Type of the left-hand side sparse matrix 810 , typename MT2 > // Type of the right-hand side dense matrix 811 inline decltype(auto) 812 operator+( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs ) 813 { 814 BLAZE_FUNCTION_TRACE; 815 816 if( (*lhs).rows() != (*rhs).rows() || (*lhs).columns() != (*rhs).columns() ) { 817 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); 818 } 819 820 return dmattsmatadd( *rhs, *lhs ); 821 } 822 //************************************************************************************************* 823 824 825 826 827 //================================================================================================= 828 // 829 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS 830 // 831 //================================================================================================= 832 833 //************************************************************************************************* 834 /*! \cond BLAZE_INTERNAL */ 835 /*!\brief Addition operator for the addition of a dense matrix-transpose sparse matrix 836 // addition expression and a dense matrix (\f$ A=(B+C)+D \f$). 837 // \ingroup dense_matrix 838 // 839 // \param lhs The left-hand side dense matrix-transpose sparse matrix addition. 840 // \param rhs The right-hand side dense matrix. 841 // \return The sum of the two matrices. 842 // 843 // This operator implements a performance optimized treatment of the addition of a dense 844 // matrix-transpose sparse matrix addition expression to a dense matrix. 845 */ 846 template< typename MT1 // Type of the dense matrix of the left-hand side expression 847 , typename MT2 // Type of the sparse matrix of the left-hand side expression 848 , typename MT3 // Type of the right-hand side dense matrix 849 , bool SO > // Storage order of the right-hand side dense matrix 850 inline decltype(auto) 851 operator+( const DMatTSMatAddExpr<MT1,MT2>& lhs, const DenseMatrix<MT3,SO>& rhs ) 852 { 853 BLAZE_FUNCTION_TRACE; 854 855 return ( lhs.leftOperand() + (*rhs) ) + lhs.rightOperand(); 856 } 857 /*! \endcond */ 858 //************************************************************************************************* 859 860 861 //************************************************************************************************* 862 /*! \cond BLAZE_INTERNAL */ 863 /*!\brief Subtraction operator for the subtraction of a dense matrix-transpose sparse matrix 864 // addition expression and a dense matrix (\f$ A=(B+C)-D \f$). 865 // \ingroup dense_matrix 866 // 867 // \param lhs The left-hand side dense matrix-transpose sparse matrix addition. 868 // \param rhs The right-hand side dense matrix. 869 // \return The difference of the two matrices. 870 // 871 // This operator implements a performance optimized treatment of the subtraction of a dense 872 // matrix-transpose sparse matrix addition expression and a dense matrix. 873 */ 874 template< typename MT1 // Type of the dense matrix of the left-hand side expression 875 , typename MT2 // Type of the sparse matrix of the left-hand side expression 876 , typename MT3 // Type of the right-hand side dense matrix 877 , bool SO > // Storage order of the right-hand side dense matrix 878 inline decltype(auto) 879 operator-( const DMatTSMatAddExpr<MT1,MT2>& lhs, const DenseMatrix<MT3,SO>& rhs ) 880 { 881 BLAZE_FUNCTION_TRACE; 882 883 return ( lhs.leftOperand() - (*rhs) ) + lhs.rightOperand(); 884 } 885 /*! \endcond */ 886 //************************************************************************************************* 887 888 } // namespace blaze 889 890 #endif 891